[jitsi~svn:9326] Fixes video problem with Google Talk on smartphone: some applications lik


#1

Hey Seb,

I am wondering if the class of a peer is the best way to determine whether
hole punch packets should be sent. We've also had issues with them breaking
SIP servers for example (we recently saw such an issue in a streamwide
environment).

Think we could find an RTP packet that is valid even if empty?

Emil

Project: jitsi
Repository: svn
Revision: 9326
Author: s_vincent
Date: 2012-01-24 09:46:30 UTC
Link:

Log Message:
------------
Fixes video problem with Google Talk on smartphone: some applications

like Vtok do not like to receive hole punch packet (zero length UDP packet).

Revisions:
----------
9326

Modified Paths:
---------------

trunk/src/net/java/sip/communicator/impl/neomedia/device/DeviceConfiguration.java

trunk/src/net/java/sip/communicator/impl/protocol/jabber/CallGTalkImpl.java

trunk/src/net/java/sip/communicator/impl/protocol/jabber/TransportManagerGTalkImpl.java

trunk/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetVideoTelephonyJabberImpl.java

Diffs:
------
Index:

trunk/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetVideoTelephonyJabberImpl.java

===================================================================
---

trunk/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetVideoTelephonyJabberImpl.java
(revision 9325)

+++

trunk/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetVideoTelephonyJabberImpl.java
(revision 9326)

@@ -166,7 +166,10 @@
     */
    public QualityControl getQualityControl(CallPeer peer)
    {
- return ((CallPeerJabberImpl) peer).getMediaHandler().
- getQualityControl();
+ if(peer instanceof CallPeerJabberImpl)
+ return ((CallPeerJabberImpl) peer).getMediaHandler().
+ getQualityControl();
+ else
+ return null;
    }
}
Index:

trunk/src/net/java/sip/communicator/impl/protocol/jabber/TransportManagerGTalkImpl.java

===================================================================
---

trunk/src/net/java/sip/communicator/impl/protocol/jabber/TransportManagerGTalkImpl.java
    (revision 9325)

+++

trunk/src/net/java/sip/communicator/impl/protocol/jabber/TransportManagerGTalkImpl.java
    (revision 9326)

@@ -1315,6 +1315,25 @@
    }

    /**
+ * Send empty UDP packet to target destination data/control ports
+ * in order to open port on NAT or RTP proxy if any.
+ *
+ * @param target <tt>MediaStreamTarget</tt>
+ * @param type the {@link MediaType} of the connector we'd like to

send

+ * the hole punching packet through.
+ */
+ @Override
+ public void sendHolePunchPacket(MediaStreamTarget target, MediaType

type)

+ {
+ /* Override TransportManager.sendHolePunchPacket that send zero

length

+ * UDP packet and do nothing instead. For some applications

(especially

+ * those installed on smartphones like Android ones), the zero

length

+ * UDP packet can confuse them.
+ */
+ return;
+ }
+
+ /**
     * Close this transport manager and release resources.
     */
    public void close()
Index:

trunk/src/net/java/sip/communicator/impl/protocol/jabber/CallGTalkImpl.java

===================================================================
---

trunk/src/net/java/sip/communicator/impl/protocol/jabber/CallGTalkImpl.java
(revision 9325)

+++

trunk/src/net/java/sip/communicator/impl/protocol/jabber/CallGTalkImpl.java
(revision 9326)

@@ -30,8 +30,8 @@
    /**
     * If the first callPeer is a Google Voice (without resource) ones.
     */
- private boolean firstCallPeerIsGV = false;
-
+ private boolean firstCallPeerIsGV = false;
+
    /**
     * Initializes a new <tt>CallGTalkImpl</tt> instance belonging to
     * <tt>sourceProvider</tt> and associated with the jingle session

with the

@@ -167,7 +167,7 @@
        if(!firstCallPeerIsGV)
            firstCallPeerIsGV = calleeJID.endsWith(
                ProtocolProviderServiceJabberImpl.GOOGLE_VOICE_DOMAIN);
-
+
        addCallPeer(callPeer);

        callPeer.setState(CallPeerState.INITIATING_CALL);
@@ -185,21 +185,21 @@
                Iterator<CallPeerGTalkImpl> it =
                    getCallPeersVector().iterator();
                String sub = calleeJID.substring(0,

calleeJID.indexOf("/"));

-
+
                // remove Google Voice first call from CallPeer vector

otherwise

                // we will display a conference call window
                while(it.hasNext())
                {
                    CallPeer p = it.next();
-
+
                    if(p.getAddress().equals(sub))
                    {
                        it.remove();
                        break;
- }
+ }
                }
            }
-
+
            parentOpSet.fireCallEvent(CallEvent.CALL_INITIATED, this);
        }

Index:

trunk/src/net/java/sip/communicator/impl/neomedia/device/DeviceConfiguration.java

===================================================================
---

trunk/src/net/java/sip/communicator/impl/neomedia/device/DeviceConfiguration.java
  (revision 9325)

+++

trunk/src/net/java/sip/communicator/impl/neomedia/device/DeviceConfiguration.java
  (revision 9326)

@@ -36,7 +36,7 @@
@SuppressWarnings("unchecked")
public class DeviceConfiguration
    extends PropertyChangeNotifier
- implements PropertyChangeListener,
+ implements PropertyChangeListener,
               PortAudioDeviceChangedCallback
{

@@ -292,6 +292,8 @@
                //QCIF
                new Dimension(176, 144),
                // QVGA
+ new Dimension(320, 200),
+ // QVGA
                new Dimension(320, 240),
                //CIF
                new Dimension(352, 288),
@@ -1298,7 +1300,7 @@
            videoMaxBandwidth = -1;
        }
    }
-
+
    /**
     * Detects audio capture devices configured through JMF and disable

audio if

     * none was found.
@@ -1307,10 +1309,10 @@
    {
        ConfigurationService config
            = NeomediaActivator.getConfigurationService();
-
+
        if (logger.isInfoEnabled())
            logger.info("Scanning for configured Audio Devices.");
-
+
        CaptureDeviceInfo[] audioCaptureDevices =
            getAvailableAudioCaptureDevices();
        if (config.getBoolean(PROP_AUDIO_DEVICE_IS_DISABLED, false))
@@ -1329,9 +1331,9 @@
            if (logger.isDebugEnabled())
                logger.debug("Found " + audioCaptureDevices.length
                + " capture devices: " + audioCaptureDevices);
-
+
            String audioDevName = config.getString(PROP_AUDIO_DEVICE);
-
+
            if(audioDevName == null || audioDevName.equals(AUDIO_NONE))
            {
                // the default behaviour if nothing set is to use

PortAudio

@@ -1369,7 +1371,7 @@
                        break;
                    }
                }
-
+
                if(getAudioSystem() == null ||

!PortAudioAuto.isSupported())

                {
                    logger.warn("Computer sound config changed or " +
@@ -1387,7 +1389,7 @@
                    + " as an audio capture device.");
        }
    }
-
+
    /**
     * Detects video capture devices configured through JMF and disable

video if

···

On Tuesday, January 24, 2012, <s_vincent@java.net> wrote:

     * none was found.
@@ -1396,7 +1398,7 @@
    {
        ConfigurationService config
            = NeomediaActivator.getConfigurationService();
-
+
        if (config.getBoolean(PROP_VIDEO_DEVICE_IS_DISABLED, false))
            videoCaptureDevice = null;
        else
@@ -1425,7 +1427,7 @@
                    logger.info("No Video Device was found.");
        }
    }
-
+
    /**
     * Callback when PortAudio device changed.
     */

--
Emil Ivov, Ph.D. 67000 Strasbourg,
Project Lead France
Jitsi
emcho@jitsi.org PHONE: +33.1.77.62.43.30
http://jitsi.org FAX: +33.1.77.62.47.31


#2

Hi Emil,

Le 24/01/12 11:09, Emil Ivov a �crit :

Hey Seb,

I am wondering if the class of a peer is the best way to determine whether hole punch packets should be sent. We've also had issues with them breaking SIP servers for example (we recently saw such an issue in a streamwide environment).

Think we could find an RTP packet that is valid even if empty?

Yes, I will make some tests with payload like RTP.

···

--
Seb

Emil

On Tuesday, January 24, 2012, <s_vincent@java.net > <mailto:s_vincent@java.net>> wrote:
> Project: jitsi
> Repository: svn
> Revision: 9326
> Author: s_vincent
> Date: 2012-01-24 09:46:30 UTC
> Link:
>
> Log Message:
> ------------
> Fixes video problem with Google Talk on smartphone: some applications like Vtok do not like to receive hole punch packet (zero length UDP packet).
>
> Revisions:
> ----------
> 9326
>
> Modified Paths:
> ---------------
> trunk/src/net/java/sip/communicator/impl/neomedia/device/DeviceConfiguration.java
> trunk/src/net/java/sip/communicator/impl/protocol/jabber/CallGTalkImpl.java
> trunk/src/net/java/sip/communicator/impl/protocol/jabber/TransportManagerGTalkImpl.java
> trunk/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetVideoTelephonyJabberImpl.java
>
> Diffs:
> ------
> Index: trunk/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetVideoTelephonyJabberImpl.java
> ===================================================================
> --- trunk/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetVideoTelephonyJabberImpl.java (revision 9325)
> +++ trunk/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetVideoTelephonyJabberImpl.java (revision 9326)
> @@ -166,7 +166,10 @@
> */
> public QualityControl getQualityControl(CallPeer peer)
> {
> - return ((CallPeerJabberImpl) peer).getMediaHandler().
> - getQualityControl();
> + if(peer instanceof CallPeerJabberImpl)
> + return ((CallPeerJabberImpl) peer).getMediaHandler().
> + getQualityControl();
> + else
> + return null;
> }
> }
> Index: trunk/src/net/java/sip/communicator/impl/protocol/jabber/TransportManagerGTalkImpl.java
> ===================================================================
> --- trunk/src/net/java/sip/communicator/impl/protocol/jabber/TransportManagerGTalkImpl.java (revision 9325)
> +++ trunk/src/net/java/sip/communicator/impl/protocol/jabber/TransportManagerGTalkImpl.java (revision 9326)
> @@ -1315,6 +1315,25 @@
> }
>
> /**
> + * Send empty UDP packet to target destination data/control ports
> + * in order to open port on NAT or RTP proxy if any.
> + *
> + * @param target <tt>MediaStreamTarget</tt>
> + * @param type the {@link MediaType} of the connector we'd like to send
> + * the hole punching packet through.
> + */
> + @Override
> + public void sendHolePunchPacket(MediaStreamTarget target, MediaType type)
> + {
> + /* Override TransportManager.sendHolePunchPacket that send zero length
> + * UDP packet and do nothing instead. For some applications (especially
> + * those installed on smartphones like Android ones), the zero length
> + * UDP packet can confuse them.
> + */
> + return;
> + }
> +
> + /**
> * Close this transport manager and release resources.
> */
> public void close()
> Index: trunk/src/net/java/sip/communicator/impl/protocol/jabber/CallGTalkImpl.java
> ===================================================================
> --- trunk/src/net/java/sip/communicator/impl/protocol/jabber/CallGTalkImpl.java (revision 9325)
> +++ trunk/src/net/java/sip/communicator/impl/protocol/jabber/CallGTalkImpl.java (revision 9326)
> @@ -30,8 +30,8 @@
> /**
> * If the first callPeer is a Google Voice (without resource) ones.
> */
> - private boolean firstCallPeerIsGV = false;
> -
> + private boolean firstCallPeerIsGV = false;
> +
> /**
> * Initializes a new <tt>CallGTalkImpl</tt> instance belonging to
> * <tt>sourceProvider</tt> and associated with the jingle session with the
> @@ -167,7 +167,7 @@
> if(!firstCallPeerIsGV)
> firstCallPeerIsGV = calleeJID.endsWith(
> ProtocolProviderServiceJabberImpl.GOOGLE_VOICE_DOMAIN);
> -
> +
> addCallPeer(callPeer);
>
> callPeer.setState(CallPeerState.INITIATING_CALL);
> @@ -185,21 +185,21 @@
> Iterator<CallPeerGTalkImpl> it =
> getCallPeersVector().iterator();
> String sub = calleeJID.substring(0, calleeJID.indexOf("/"));
> -
> +
> // remove Google Voice first call from CallPeer vector otherwise
> // we will display a conference call window
> while(it.hasNext())
> {
> CallPeer p = it.next();
> -
> +
> if(p.getAddress().equals(sub))
> {
> it.remove();
> break;
> - }
> + }
> }
> }
> -
> +
> parentOpSet.fireCallEvent(CallEvent.CALL_INITIATED, this);
> }
>
> Index: trunk/src/net/java/sip/communicator/impl/neomedia/device/DeviceConfiguration.java
> ===================================================================
> --- trunk/src/net/java/sip/communicator/impl/neomedia/device/DeviceConfiguration.java (revision 9325)
> +++ trunk/src/net/java/sip/communicator/impl/neomedia/device/DeviceConfiguration.java (revision 9326)
> @@ -36,7 +36,7 @@
> @SuppressWarnings("unchecked")
> public class DeviceConfiguration
> extends PropertyChangeNotifier
> - implements PropertyChangeListener,
> + implements PropertyChangeListener,
> PortAudioDeviceChangedCallback
> {
>
> @@ -292,6 +292,8 @@
> //QCIF
> new Dimension(176, 144),
> // QVGA
> + new Dimension(320, 200),
> + // QVGA
> new Dimension(320, 240),
> //CIF
> new Dimension(352, 288),
> @@ -1298,7 +1300,7 @@
> videoMaxBandwidth = -1;
> }
> }
> -
> +
> /**
> * Detects audio capture devices configured through JMF and disable audio if
> * none was found.
> @@ -1307,10 +1309,10 @@
> {
> ConfigurationService config
> = NeomediaActivator.getConfigurationService();
> -
> +
> if (logger.isInfoEnabled())
> logger.info <http://logger.info>("Scanning for configured Audio Devices.");
> -
> +
> CaptureDeviceInfo[] audioCaptureDevices =
> getAvailableAudioCaptureDevices();
> if (config.getBoolean(PROP_AUDIO_DEVICE_IS_DISABLED, false))
> @@ -1329,9 +1331,9 @@
> if (logger.isDebugEnabled())
> logger.debug("Found " + audioCaptureDevices.length
> + " capture devices: " + audioCaptureDevices);
> -
> +
> String audioDevName = config.getString(PROP_AUDIO_DEVICE);
> -
> +
> if(audioDevName == null || audioDevName.equals(AUDIO_NONE))
> {
> // the default behaviour if nothing set is to use PortAudio
> @@ -1369,7 +1371,7 @@
> break;
> }
> }
> -
> +
> if(getAudioSystem() == null || !PortAudioAuto.isSupported())
> {
> logger.warn("Computer sound config changed or " +
> @@ -1387,7 +1389,7 @@
> + " as an audio capture device.");
> }
> }
> -
> +
> /**
> * Detects video capture devices configured through JMF and disable video if
> * none was found.
> @@ -1396,7 +1398,7 @@
> {
> ConfigurationService config
> = NeomediaActivator.getConfigurationService();
> -
> +
> if (config.getBoolean(PROP_VIDEO_DEVICE_IS_DISABLED, false))
> videoCaptureDevice = null;
> else
> @@ -1425,7 +1427,7 @@
> logger.info <http://logger.info>("No Video Device was found.");
> }
> }
> -
> +
> /**
> * Callback when PortAudio device changed.
> */
>

--
Emil Ivov, Ph.D. 67000 Strasbourg,
Project Lead France
Jitsi
emcho@jitsi.org <mailto:emcho@jitsi.org> PHONE: +33.1.77.62.43.30
http://jitsi.org FAX: +33.1.77.62.47.31