aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/java/sip
diff options
context:
space:
mode:
authorDamian Minkov <damencho@jitsi.org>2011-06-03 10:36:19 +0000
committerDamian Minkov <damencho@jitsi.org>2011-06-03 10:36:19 +0000
commit6064f8d33cabe5b9fa5aa9f26f48c15091004ee5 (patch)
tree4f672d66c69002c2453524bb5a1fabb3a73b33e1 /src/net/java/sip
parent754f0397d2cca565f498dc15328e32743c11f22b (diff)
downloadjitsi-6064f8d33cabe5b9fa5aa9f26f48c15091004ee5.zip
jitsi-6064f8d33cabe5b9fa5aa9f26f48c15091004ee5.tar.gz
jitsi-6064f8d33cabe5b9fa5aa9f26f48c15091004ee5.tar.bz2
Initial video size setting, when creating video call.
Hide resize button if we can detect that its not supported, and limit the resolutions we have for setting according the remote party settings. Fix changing resolution several times. Fix duplicate field for keeping framerate.
Diffstat (limited to 'src/net/java/sip')
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/CallManager.java36
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java24
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java2
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/ResizeVideoButton.java89
-rw-r--r--src/net/java/sip/communicator/impl/neomedia/MediaUtils.java10
-rw-r--r--src/net/java/sip/communicator/impl/neomedia/VideoMediaStreamImpl.java141
-rw-r--r--src/net/java/sip/communicator/impl/neomedia/device/AudioMixerMediaDevice.java7
-rw-r--r--src/net/java/sip/communicator/impl/neomedia/device/MediaDeviceImpl.java42
-rw-r--r--src/net/java/sip/communicator/impl/neomedia/format/VideoMediaFormatImpl.java16
-rw-r--r--src/net/java/sip/communicator/impl/protocol/icq/ProtocolProviderServiceIcqImpl.java2
-rw-r--r--src/net/java/sip/communicator/impl/protocol/sip/CallPeerMediaHandlerSipImpl.java109
-rw-r--r--src/net/java/sip/communicator/impl/protocol/sip/CallPeerSipImpl.java25
-rw-r--r--src/net/java/sip/communicator/impl/protocol/sip/CallSipImpl.java25
-rw-r--r--src/net/java/sip/communicator/impl/protocol/sip/OperationSetVideoTelephonySipImpl.java71
-rw-r--r--src/net/java/sip/communicator/impl/protocol/sip/QualityControlsWrapper.java180
-rw-r--r--src/net/java/sip/communicator/impl/protocol/sip/sdp/SdpUtils.java38
-rw-r--r--src/net/java/sip/communicator/service/neomedia/QualityControls.java53
-rw-r--r--src/net/java/sip/communicator/service/neomedia/QualityPreset.java76
-rw-r--r--src/net/java/sip/communicator/service/neomedia/QualityPresets.java106
-rw-r--r--src/net/java/sip/communicator/service/neomedia/VideoMediaStream.java6
-rw-r--r--src/net/java/sip/communicator/service/neomedia/device/MediaDevice.java8
-rw-r--r--src/net/java/sip/communicator/service/protocol/OperationSetVideoTelephony.java58
-rw-r--r--src/net/java/sip/communicator/service/protocol/media/AbstractOperationSetVideoTelephony.java68
-rw-r--r--src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java14
24 files changed, 1008 insertions, 198 deletions
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/CallManager.java b/src/net/java/sip/communicator/impl/gui/main/call/CallManager.java
index 502d475..c553415 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/CallManager.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/CallManager.java
@@ -893,21 +893,43 @@ public class CallManager
}
/**
+ * Checks whether the <tt>callPeer</tt> supports setting video
+ * quality presets. If quality controls is null, its not supported.
+ * @param callPeer the peer, which video quality we're checking
+ * @return whether call peer supports setting quality preset.
+ */
+ public static boolean isVideoQualityPresetSupported(CallPeer callPeer)
+ {
+ ProtocolProviderService provider = callPeer.getProtocolProvider();
+ OperationSetVideoTelephony videoOpSet
+ = provider.getOperationSet(OperationSetVideoTelephony.class);
+
+ if (videoOpSet == null)
+ return false;
+
+ return videoOpSet.getQualityControls(callPeer) != null;
+ }
+
+ /**
* Sets the given quality preset for the video of the given call peer.
*
* @param callPeer the peer, which video quality we're setting
* @param qualityPreset the new quality settings
*/
public static void setVideoQualityPreset(final CallPeer callPeer,
- final QualityPreset qualityPreset)
+ final QualityPresets qualityPreset)
{
-
ProtocolProviderService provider = callPeer.getProtocolProvider();
final OperationSetVideoTelephony videoOpSet
- = (OperationSetVideoTelephony) provider
- .getOperationSet(OperationSetVideoTelephony.class);
+ = provider.getOperationSet(OperationSetVideoTelephony.class);
+
+ if (videoOpSet == null)
+ return;
+
+ final QualityControls qualityControl =
+ videoOpSet.getQualityControls(callPeer);
- if (videoOpSet != null)
+ if (qualityControl != null)
{
new Thread(new Runnable()
{
@@ -915,8 +937,8 @@ public class CallManager
{
try
{
- videoOpSet.setQualityPreset(
- callPeer, qualityPreset);
+ qualityControl.setPreferredRemoteSendMaxPreset(
+ qualityPreset);
}
catch(OperationFailedException e)
{
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java
index d63df98..75dfd14 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java
@@ -277,7 +277,6 @@ public class CallPanel
recordButton = new RecordButton(call);
videoButton = new LocalVideoButton(call);
showHideVideoButton = new ShowHideVideoButton(call);
- resizeVideoButton = new ResizeVideoButton(call);
showHideVideoButton.setPeerRenderer(((CallRenderer) callPanel)
.getCallPeerRenderer(call.getCallPeers().next()));
@@ -1044,20 +1043,30 @@ public class CallPanel
/**
* Adds remote video specific components.
*/
- public void addRemoteVideoSpecificComponents()
+ public void addRemoteVideoSpecificComponents(CallPeer callPeer)
{
- settingsPanel.add(resizeVideoButton);
+ if(CallManager.isVideoQualityPresetSupported(callPeer))
+ {
+ if(resizeVideoButton == null)
+ resizeVideoButton = new ResizeVideoButton(call);
+
+ if(resizeVideoButton.countAvailableOptions() > 1)
+ settingsPanel.add(resizeVideoButton);
+ }
+
settingsPanel.add(fullScreenButton);
settingsPanel.revalidate();
settingsPanel.repaint();
}
/**
- * Adds remote video specific components.
+ * Remove remote video specific components.
*/
public void removeRemoteVideoSpecificComponents()
{
- settingsPanel.remove(resizeVideoButton);
+ if(resizeVideoButton != null)
+ settingsPanel.remove(resizeVideoButton);
+
settingsPanel.remove(fullScreenButton);
settingsPanel.revalidate();
settingsPanel.repaint();
@@ -1103,7 +1112,10 @@ public class CallPanel
settingsPanel.remove(videoButton);
settingsPanel.remove(showHideVideoButton);
- settingsPanel.remove(resizeVideoButton);
+
+ if(resizeVideoButton != null)
+ settingsPanel.remove(resizeVideoButton);
+
settingsPanel.remove(desktopSharingButton);
settingsPanel.remove(transferCallButton);
settingsPanel.remove(fullScreenButton);
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java
index ef4193e..75c88f8 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java
@@ -974,7 +974,7 @@ public class OneToOneCallPeerPanel
videoContainer.add(video, VideoLayout.CENTER_REMOTE, 0);
callRenderer.getCallContainer()
- .addRemoteVideoSpecificComponents();
+ .addRemoteVideoSpecificComponents(callPeer);
}
else
{
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/ResizeVideoButton.java b/src/net/java/sip/communicator/impl/gui/main/call/ResizeVideoButton.java
index 4cd7aaf..b40325b 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/ResizeVideoButton.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/ResizeVideoButton.java
@@ -13,7 +13,7 @@ import javax.swing.*;
import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.utils.*;
-import net.java.sip.communicator.service.neomedia.QualityPreset;
+import net.java.sip.communicator.service.neomedia.*;
import net.java.sip.communicator.service.protocol.*;
/**
@@ -25,6 +25,21 @@ public class ResizeVideoButton
extends AbstractCallToggleButton
{
/**
+ * Is low option present in menu when button is pressed.
+ */
+ private boolean loOptionPresent = false;
+
+ /**
+ * Is SD option present in menu when button is pressed.
+ */
+ private boolean sdOptionPresent = false;
+
+ /**
+ * Is HD option present in menu when button is pressed.
+ */
+ private boolean hdOptionPresent = false;
+
+ /**
* Initializes a new <tt>DesktopSharingButton</tt> instance which is meant
* to be used to initiate a desktop sharing during a call.
*
@@ -49,11 +64,42 @@ public class ResizeVideoButton
*/
public ResizeVideoButton(Call call, boolean fullScreen, boolean selected)
{
- super( call,
+ super(call,
fullScreen,
selected,
ImageLoader.SD_VIDEO_BUTTON,
"service.gui.CHANGE_VIDEO_QUALITY");
+
+ // catch everything, make sure we don't interrupt gui creation
+ // if anything strange happens
+ try
+ {
+ CallPeer peer = call.getCallPeers().next();
+ OperationSetVideoTelephony videoOpSet = peer.getProtocolProvider()
+ .getOperationSet(OperationSetVideoTelephony.class);
+
+ QualityControls qualityControls = videoOpSet.getQualityControls(peer);
+ QualityPresets maxRemotePreset =
+ qualityControls.getRemoteSendMaxPreset();
+
+ // if there is a setting for max preset lets look at it
+ // and add only those presets that are remotely supported
+ if( maxRemotePreset == null ||
+ maxRemotePreset.compareTo(QualityPresets.HD_QUALITY) >= 0)
+ hdOptionPresent = true;
+
+ if( maxRemotePreset == null ||
+ maxRemotePreset.compareTo(QualityPresets.SD_QUALITY) >= 0)
+ sdOptionPresent = true;
+
+ if( maxRemotePreset == null ||
+ maxRemotePreset.compareTo(QualityPresets.LO_QUALITY) >= 0)
+ loOptionPresent = true;
+ }
+ catch(Throwable t)
+ {
+ // do nothing
+ }
}
/**
@@ -93,9 +139,9 @@ public class ResizeVideoButton
popupMenu.setInvoker(this);
popupMenu.setFocusable(true);
- Dimension loDimension = QualityPreset.LO_QUALITY.getResolution();
- Dimension sdDimension = QualityPreset.SD_QUALITY.getResolution();
- Dimension hdDimension = QualityPreset.HD_QUALITY.getResolution();
+ Dimension loDimension = QualityPresets.LO_QUALITY.getResolution();
+ Dimension sdDimension = QualityPresets.SD_QUALITY.getResolution();
+ Dimension hdDimension = QualityPresets.HD_QUALITY.getResolution();
JMenuItem lowQuality = new JMenuItem(
GuiActivator.getResources()
@@ -124,9 +170,15 @@ public class ResizeVideoButton
titleLabel.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0));
popupMenu.add(titleLabel);
popupMenu.addSeparator();
- popupMenu.add(hdQuality);
- popupMenu.add(normalQuality);
- popupMenu.add(lowQuality);
+
+ if(hdOptionPresent)
+ popupMenu.add(hdQuality);
+
+ if(sdOptionPresent)
+ popupMenu.add(normalQuality);
+
+ if(loOptionPresent)
+ popupMenu.add(lowQuality);
lowQuality.addActionListener(new ActionListener()
{
@@ -138,7 +190,7 @@ public class ResizeVideoButton
CallManager.setVideoQualityPreset(
call.getCallPeers().next(),
- QualityPreset.LO_QUALITY);
+ QualityPresets.LO_QUALITY);
}
});
@@ -151,7 +203,7 @@ public class ResizeVideoButton
setIconImageID(ImageLoader.SD_VIDEO_BUTTON);
CallManager.setVideoQualityPreset(
- call.getCallPeers().next(), QualityPreset.SD_QUALITY);
+ call.getCallPeers().next(), QualityPresets.SD_QUALITY);
}
});
@@ -164,7 +216,7 @@ public class ResizeVideoButton
setIconImageID(ImageLoader.HD_VIDEO_BUTTON);
CallManager.setVideoQualityPreset(
- call.getCallPeers().next(), QualityPreset.HD_QUALITY);
+ call.getCallPeers().next(), QualityPresets.HD_QUALITY);
}
});
@@ -181,4 +233,19 @@ public class ResizeVideoButton
{
return " (" + (int) d.getWidth() + "x" + (int) d.getHeight() + ")";
}
+
+ /**
+ * Check the available options that will be shown
+ * when button is pressed.
+ * @return the number of options.
+ */
+ public int countAvailableOptions()
+ {
+ int count = 0;
+ if(loOptionPresent) count++;
+ if(sdOptionPresent) count++;
+ if(hdOptionPresent) count++;
+
+ return count;
+ }
}
diff --git a/src/net/java/sip/communicator/impl/neomedia/MediaUtils.java b/src/net/java/sip/communicator/impl/neomedia/MediaUtils.java
index 97598c7..444504d 100644
--- a/src/net/java/sip/communicator/impl/neomedia/MediaUtils.java
+++ b/src/net/java/sip/communicator/impl/neomedia/MediaUtils.java
@@ -616,11 +616,17 @@ public class MediaUtils
if(sendSize != null)
{
/* single value => send [x=width,y=height] */
- img.append("send [x=");
+ /*img.append("send [x=");
img.append((int)sendSize.getWidth());
img.append(",y=");
img.append((int)sendSize.getHeight());
- img.append("]");
+ img.append("]");*/
+ /* send [x=[min-max],y=[min-max]] */
+ img.append("send [x=[0-");
+ img.append((int)sendSize.getWidth());
+ img.append("],y=[0-");
+ img.append((int)sendSize.getHeight());
+ img.append("]]");
/*
else
{
diff --git a/src/net/java/sip/communicator/impl/neomedia/VideoMediaStreamImpl.java b/src/net/java/sip/communicator/impl/neomedia/VideoMediaStreamImpl.java
index f600f15..5beecaf 100644
--- a/src/net/java/sip/communicator/impl/neomedia/VideoMediaStreamImpl.java
+++ b/src/net/java/sip/communicator/impl/neomedia/VideoMediaStreamImpl.java
@@ -22,6 +22,7 @@ import net.java.sip.communicator.service.neomedia.*;
import net.java.sip.communicator.service.neomedia.device.*;
import net.java.sip.communicator.service.neomedia.format.*;
import net.java.sip.communicator.service.neomedia.event.*;
+import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.*;
/**
@@ -55,6 +56,11 @@ public class VideoMediaStreamImpl
private boolean usePLI = false;
/**
+ * This stream quality control.
+ */
+ private QualityControlsImpl qualityControls = new QualityControlsImpl();
+
+ /**
* Selects the <tt>VideoFormat</tt> from the list of supported formats of a
* specific video <tt>DataSource</tt> which has a size as close as possible
* to a specific size and sets it as the format of the specified video
@@ -584,6 +590,9 @@ public class VideoMediaStreamImpl
if(res != null)
{
outputSize = res[1];
+
+ qualityControls.setRemoteSendMaxPreset(new QualityPresets(res[0]));
+ qualityControls.setRemoteReceiveResolution(outputSize);
((VideoMediaDeviceSession)getDeviceSession()).
setOutputSize(outputSize);
}
@@ -807,4 +816,136 @@ public class VideoMediaStreamImpl
{
return 5;
}
+
+ /**
+ * Returns the quality control for this stream.
+ * @return
+ */
+ public QualityControls getQualityControls()
+ {
+ return qualityControls;
+ }
+
+ /**
+ * The quality control implementation used for
+ * this video stream quality control.
+ */
+ private class QualityControlsImpl
+ implements QualityControls
+ {
+ /**
+ * The current used preset.
+ */
+ private QualityPresets preset;
+
+ /**
+ * The minimum values for resolution, framerate ...
+ */
+ private QualityPresets minPreset;
+
+ /**
+ * The maximum values for resolution, framerate ...
+ */
+ private QualityPresets maxPreset;
+
+ /**
+ * This is the local settings from the config panel.
+ */
+ private QualityPresets localSettingsPreset;
+
+ /**
+ * Sets the preset.
+ * @param preset the desired video settings
+ * @throws OperationFailedException
+ */
+ private void setRemoteReceivePreset(QualityPresets preset)
+ throws
+ OperationFailedException
+ {
+ if(preset.compareTo(getPreferredSendPreset()) > 0)
+ this.preset = getPreferredSendPreset();
+ else
+ this.preset = preset;
+ }
+
+ /**
+ * The current preset.
+ * @return
+ */
+ public QualityPresets getRemoteReceivePreset()
+ {
+ return preset;
+ }
+
+ /**
+ * The minimum resolution values for remote part.
+ * @return
+ */
+ public QualityPresets getRemoteSendMinPreset()
+ {
+ return minPreset;
+ }
+
+ /**
+ * The max resolution values for remote part.
+ * @return
+ */
+ public QualityPresets getRemoteSendMaxPreset()
+ {
+ return maxPreset;
+ }
+
+ /**
+ * Does nothing specific locally.
+ *
+ * @param preset the max preset
+ * @throws OperationFailedException not thrown.
+ */
+ public void setPreferredRemoteSendMaxPreset(QualityPresets preset)
+ throws OperationFailedException
+ {
+ setRemoteSendMaxPreset(preset);
+ }
+
+ /**
+ * Changes remote send preset, the one we will receive.
+ * @param preset
+ */
+ public void setRemoteSendMaxPreset(QualityPresets preset)
+ {
+ this.maxPreset = preset;
+ }
+
+ /**
+ * The local setting of capture.
+ * @return
+ */
+ private QualityPresets getPreferredSendPreset()
+ {
+ if(localSettingsPreset == null)
+ {
+ DeviceConfiguration deviceConfiguration =
+ NeomediaActivator.getMediaServiceImpl()
+ .getDeviceConfiguration();
+
+ localSettingsPreset = new QualityPresets(
+ deviceConfiguration.getVideoSize(),
+ deviceConfiguration.getFrameRate());
+ }
+ return localSettingsPreset;
+ }
+
+ /**
+ * Sets maximum resolution.
+ * @param res
+ */
+ public void setRemoteReceiveResolution(Dimension res)
+ {
+ try
+ {
+ this.setRemoteReceivePreset(new QualityPresets(res));
+ }
+ catch(OperationFailedException e){}
+ }
+ }
}
diff --git a/src/net/java/sip/communicator/impl/neomedia/device/AudioMixerMediaDevice.java b/src/net/java/sip/communicator/impl/neomedia/device/AudioMixerMediaDevice.java
index 8e616a2..5ff7ac2 100644
--- a/src/net/java/sip/communicator/impl/neomedia/device/AudioMixerMediaDevice.java
+++ b/src/net/java/sip/communicator/impl/neomedia/device/AudioMixerMediaDevice.java
@@ -415,11 +415,12 @@ public class AudioMixerMediaDevice
/**
* Gets a list of <tt>MediaFormat</tt>s supported by this
* <tt>MediaDevice</tt>. Currently does nothing.
- * @param preset does nothing for audio.
+ * @param sendPreset does nothing for audio.
* @return the list of <tt>MediaFormat</tt>s supported by this device
* @see MediaDevice#getSupportedFormats()
*/
- public List<MediaFormat> getSupportedFormats(QualityPreset preset)
+ public List<MediaFormat> getSupportedFormats(QualityPresets sendPreset,
+ QualityPresets receivePreset)
{
return device.getSupportedFormats();
}
@@ -432,7 +433,7 @@ public class AudioMixerMediaDevice
*/
public List<MediaFormat> getSupportedFormats()
{
- return this.getSupportedFormats(null);
+ return this.getSupportedFormats(null, null);
}
/**
diff --git a/src/net/java/sip/communicator/impl/neomedia/device/MediaDeviceImpl.java b/src/net/java/sip/communicator/impl/neomedia/device/MediaDeviceImpl.java
index 50b854a..2d695bc 100644
--- a/src/net/java/sip/communicator/impl/neomedia/device/MediaDeviceImpl.java
+++ b/src/net/java/sip/communicator/impl/neomedia/device/MediaDeviceImpl.java
@@ -6,8 +6,10 @@
*/
package net.java.sip.communicator.impl.neomedia.device;
+import java.awt.*;
import java.io.*;
import java.util.*;
+import java.util.List;
import javax.media.*;
import javax.media.control.*;
@@ -323,17 +325,18 @@ public class MediaDeviceImpl
*/
public List<MediaFormat> getSupportedFormats()
{
- return this.getSupportedFormats(null);
+ return this.getSupportedFormats(null, null);
}
/**
* Gets a list of <tt>MediaFormat</tt>s supported by this
* <tt>MediaDevice</tt>.
- * @param preset the preset used to set some of the format parameters,
+ * @param sendPreset the preset used to set some of the format parameters,
* used for video and settings.
* @return the list of <tt>MediaFormat</tt>s supported by this device
* @see MediaDevice#getSupportedFormats()
*/
- public List<MediaFormat> getSupportedFormats(QualityPreset preset)
+ public List<MediaFormat> getSupportedFormats(QualityPresets sendPreset,
+ QualityPresets receivePreset)
{
EncodingConfiguration encodingConfiguration
= NeomediaActivator
@@ -348,7 +351,6 @@ public class MediaDeviceImpl
// if there is preset check and set the format attributes
// where needed
- if(preset != null)
{
MediaFormat customFormat = null;
MediaFormat toRemove = null;
@@ -361,9 +363,37 @@ public class MediaDeviceImpl
if(h264AdvancedAttributes == null)
h264AdvancedAttributes = new HashMap<String, String>();
+ Dimension sendSize = null;
+ Dimension receiveSize;
+
+ // change send size only for video calls
+ if(!captureDeviceInfo.getLocator().getProtocol().equals(
+ ImageStreamingAuto.LOCATOR_PROTOCOL))
+ {
+ if(sendPreset != null)
+ sendSize = sendPreset.getResolution();
+ else
+ sendSize = NeomediaActivator.getMediaServiceImpl()
+ .getDeviceConfiguration().getVideoSize();
+ }
+
+ // if there is specified preset, send its settings
+ if(receivePreset != null)
+ receiveSize = receivePreset.getResolution();
+ else
+ {
+ // or just send the max video resolution of the PC
+ // as we do by default
+ ScreenDevice screen
+ = NeomediaActivator.getMediaServiceImpl()
+ .getDefaultScreenDevice();
+ receiveSize = (screen == null) ?
+ null : screen.getSize();
+ }
+
h264AdvancedAttributes.put("imageattr",
- MediaUtils.createImageAttr(null,
- preset.getResolution()));
+ MediaUtils.createImageAttr(sendSize,
+ receiveSize));
customFormat = NeomediaActivator.getMediaServiceImpl()
.getFormatFactory().createMediaFormat(
diff --git a/src/net/java/sip/communicator/impl/neomedia/format/VideoMediaFormatImpl.java b/src/net/java/sip/communicator/impl/neomedia/format/VideoMediaFormatImpl.java
index d576536..cfbc2bb 100644
--- a/src/net/java/sip/communicator/impl/neomedia/format/VideoMediaFormatImpl.java
+++ b/src/net/java/sip/communicator/impl/neomedia/format/VideoMediaFormatImpl.java
@@ -36,11 +36,6 @@ public class VideoMediaFormatImpl
private final double clockRate;
/**
- * The frame rate of this <tt>VideoMediaFormat</tt>.
- */
- private float frameRate;
-
- /**
* Initializes a new <tt>VideoMediaFormatImpl</tt> instance with a specific
* encoding.
*
@@ -117,10 +112,15 @@ public class VideoMediaFormatImpl
Map<String, String> formatParameters,
Map<String, String> advancedParameters)
{
- super(format, formatParameters, advancedParameters);
+ super(new VideoFormat(
+ format.getEncoding(),
+ format.getSize(),
+ format.getMaxDataLength(),
+ format.getDataType(),
+ frameRate
+ ), formatParameters, advancedParameters);
this.clockRate = clockRate;
- this.frameRate = frameRate;
}
/**
@@ -260,7 +260,7 @@ public class VideoMediaFormatImpl
*/
public float getFrameRate()
{
- return frameRate;
+ return format.getFrameRate();
}
/**
diff --git a/src/net/java/sip/communicator/impl/protocol/icq/ProtocolProviderServiceIcqImpl.java b/src/net/java/sip/communicator/impl/protocol/icq/ProtocolProviderServiceIcqImpl.java
index d111d2b..2f3f1b5 100644
--- a/src/net/java/sip/communicator/impl/protocol/icq/ProtocolProviderServiceIcqImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/icq/ProtocolProviderServiceIcqImpl.java
@@ -133,7 +133,7 @@ public class ProtocolProviderServiceIcqImpl
*/
public RegistrationState getRegistrationState()
{
- if(getAimConnection() == null)
+ if(getAimConnection() == null || lastRegistrationState == null)
return RegistrationState.UNREGISTERED;
return lastRegistrationState;
diff --git a/src/net/java/sip/communicator/impl/protocol/sip/CallPeerMediaHandlerSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/CallPeerMediaHandlerSipImpl.java
index e46a729..ac11621 100644
--- a/src/net/java/sip/communicator/impl/protocol/sip/CallPeerMediaHandlerSipImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/sip/CallPeerMediaHandlerSipImpl.java
@@ -66,6 +66,17 @@ public class CallPeerMediaHandlerSipImpl
private final TransportManagerSipImpl transportManager;
/**
+ * Whether other party is able to change video quality settings.
+ * Normally its whether we have detected existence of imageattr in sdp.
+ */
+ boolean supportQualityControls;
+
+ /**
+ * The current quality controls for this peer media handler if any.
+ */
+ private QualityControlsWrapper qualityControls;
+
+ /**
* Creates a new handler that will be managing media streams for
* <tt>peer</tt>.
*
@@ -77,6 +88,7 @@ public class CallPeerMediaHandlerSipImpl
super(peer, peer);
transportManager = new TransportManagerSipImpl(peer);
+ qualityControls = new QualityControlsWrapper(peer);
}
/**
@@ -150,6 +162,19 @@ public class CallPeerMediaHandlerSipImpl
//Audio Media Description
Vector<MediaDescription> mediaDescs = new Vector<MediaDescription>();
+ QualityPresets sendQualityPreset = null;
+ QualityPresets receiveQualityPreset = null;
+
+ if(qualityControls != null)
+ {
+ // the one we will send is the one the other part has announced
+ // as receive
+ sendQualityPreset = qualityControls.getRemoteReceivePreset();
+ // the one we want to receive is the setting that remote
+ // can send
+ receiveQualityPreset = qualityControls.getRemoteSendMaxPreset();
+ }
+
for (MediaType mediaType : MediaType.values())
{
MediaDevice dev = getDefaultDevice(mediaType);
@@ -166,7 +191,9 @@ public class CallPeerMediaHandlerSipImpl
{
MediaDescription md =
createMediaDescription(
- dev.getSupportedFormats(videoQualityPreset),
+ dev.getSupportedFormats(
+ sendQualityPreset,
+ receiveQualityPreset),
getTransportManager().getStreamConnector(mediaType),
direction,
dev.getSupportedExtensions());
@@ -175,10 +202,12 @@ public class CallPeerMediaHandlerSipImpl
{
// if we have setting for video preset lets
// send info for the desired framerate
- if(videoQualityPreset != null)
+ if(receiveQualityPreset != null
+ && receiveQualityPreset.getFameRate() > 0)
md.setAttribute("framerate",
+ // doing only int frame rate for now
String.valueOf(
- videoQualityPreset.getFameRate()));
+ (int)receiveQualityPreset.getFameRate()));
}
catch(SdpException e)
{
@@ -451,6 +480,52 @@ public class CallPeerMediaHandlerSipImpl
mutuallySupportedFormats.get(0));
initStream(connector, dev, fmt, target, direction, rtpExtensions);
+ // check for options from remote party and set them locally
+ if(mediaType.equals(MediaType.VIDEO))
+ {
+ QualityPresets sendQualityPreset = null;
+ QualityPresets receiveQualityPreset = null;
+
+ if(qualityControls != null)
+ {
+ // the one we will send is the other party receive
+ sendQualityPreset =
+ qualityControls.getRemoteReceivePreset();
+ // the one we want to receive
+ receiveQualityPreset =
+ qualityControls.getRemoteSendMaxPreset();
+
+ mutuallySupportedFormats
+ = (dev == null)
+ ? null
+ : intersectFormats(
+ mutuallySupportedFormats,
+ dev.getSupportedFormats(
+ sendQualityPreset, receiveQualityPreset));
+ }
+
+ supportQualityControls =
+ SdpUtils.containsAttribute(mediaDescription, "imageattr");
+
+ float frameRate = -1;
+ // check for frame rate setting
+ try
+ {
+ String frStr = mediaDescription.getAttribute("framerate");
+ if(frStr != null)
+ frameRate = Integer.parseInt(frStr);
+ }
+ catch(SdpParseException e)
+ {
+ // do nothing
+ }
+
+ if(frameRate > 0)
+ {
+ qualityControls.setMaxFrameRate(frameRate);
+ }
+ }
+
MediaDescription md = createMediaDescription(
mutuallySupportedFormats, connector, direction, rtpExtensions);
@@ -771,4 +846,32 @@ public class CallPeerMediaHandlerSipImpl
{
return transportManager;
}
+
+ /**
+ * Returns the quality control for video calls if any.
+ * @return the implemented quality control.
+ */
+ public QualityControls getQualityControls()
+ {
+ if(supportQualityControls)
+ {
+ return qualityControls;
+ }
+ else
+ {
+ // we have detected that its not supported and return null
+ // and control ui won't be visible
+ return null;
+ }
+ }
+
+ /**
+ * Sometimes as initing a call with custom preset can set and we force
+ * that quality controls is supported.
+ * @param value whether quality controls is supported..
+ */
+ public void setSupportQualityControls(boolean value)
+ {
+ this.supportQualityControls = value;
+ }
}
diff --git a/src/net/java/sip/communicator/impl/protocol/sip/CallPeerSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/CallPeerSipImpl.java
index 130781a..9fef684 100644
--- a/src/net/java/sip/communicator/impl/protocol/sip/CallPeerSipImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/sip/CallPeerSipImpl.java
@@ -1356,29 +1356,4 @@ public class CallPeerSipImpl
else
setState(CallPeerState.DISCONNECTED, reason);
}
-
- /**
- * Changes video quality preset.
- * @param preset the preset to use.
- */
- public void setVideoQualityPreset(QualityPreset preset)
- throws OperationFailedException
- {
- CallPeerMediaHandlerSipImpl mediaHandler = getMediaHandler();
-
- // set the new preset
- mediaHandler.setVideoQualityPreset(preset);
-
- try
- {
- // re-invites the peer with the new settings
- sendReInvite(mediaHandler.createOffer());
- }
- catch (Exception ex)
- {
- ProtocolProviderServiceSipImpl.throwOperationFailedException(
- "Failed to create SDP offer to hold.",
- OperationFailedException.INTERNAL_ERROR, ex, logger);
- }
- }
}
diff --git a/src/net/java/sip/communicator/impl/protocol/sip/CallSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/CallSipImpl.java
index 632b622..a8de06f 100644
--- a/src/net/java/sip/communicator/impl/protocol/sip/CallSipImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/sip/CallSipImpl.java
@@ -43,6 +43,12 @@ public class CallSipImpl
private final SipMessageFactory messageFactory;
/**
+ * When starting call we may have quality preferences we must use
+ * for the call.
+ */
+ private QualityPresets initialQualityPreferences;
+
+ /**
* Crates a CallSipImpl instance belonging to <tt>sourceProvider</tt> and
* initiated by <tt>CallCreator</tt>.
*
@@ -174,6 +180,16 @@ public class CallSipImpl
callPeer.getMediaHandler().setLocalVideoTransmissionEnabled(
localVideoAllowed);
+ if(initialQualityPreferences != null)
+ {
+ // we are in situation where we init the call and we cannot
+ // determine whether the other party supports changing quality
+ // so we force it
+ callPeer.getMediaHandler().setSupportQualityControls(true);
+ callPeer.getMediaHandler().getQualityControls()
+ .setRemoteSendMaxPreset(initialQualityPreferences);
+ }
+
try
{
callPeer.invite();
@@ -378,4 +394,13 @@ public class CallSipImpl
return peer;
}
+
+ /**
+ * Set a quality preferences we may use when we start the call.
+ * @param qualityPreferences the initial quality preferences.
+ */
+ public void setInitialQualityPreferences(QualityPresets qualityPreferences)
+ {
+ this.initialQualityPreferences = qualityPreferences;
+ }
}
diff --git a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetVideoTelephonySipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetVideoTelephonySipImpl.java
index 6aad3d4..01a90e7 100644
--- a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetVideoTelephonySipImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetVideoTelephonySipImpl.java
@@ -99,10 +99,55 @@ public class OperationSetVideoTelephonySipImpl
public Call createVideoCall(String uri)
throws OperationFailedException, ParseException
{
+ return createVideoCall(uri, null);
+ }
+
+ /**
+ * Create a new video call and invite the specified CallPeer to it.
+ *
+ * @param callee the address of the callee that we should invite to a new
+ * call.
+ * @return CallPeer the CallPeer that will represented by the
+ * specified uri. All following state change events will be delivered
+ * through that call peer. The Call that this peer is a member
+ * of could be retrieved from the CallParticipatn instance with the use
+ * of the corresponding method.
+ * @throws OperationFailedException with the corresponding code if we fail
+ * to create the video call.
+ */
+ public Call createVideoCall(Contact callee)
+ throws OperationFailedException
+ {
+ return createVideoCall(callee, null);
+ }
+
+ /**
+ * Create a new video call and invite the specified CallPeer to it.
+ *
+ * @param uri the address of the callee that we should invite to a new
+ * call.
+ * @param qualityPreferences the quality preset we will use establishing
+ * the video call, and we will expect from the other side. When establishing
+ * call we don't have any indications whether remote part supports quality
+ * presets, so this setting can be ignored.
+ * @return CallPeer the CallPeer that will represented by the
+ * specified uri. All following state change events will be delivered
+ * through that call peer. The Call that this peer is a member
+ * of could be retrieved from the CallParticipatn instance with the use
+ * of the corresponding method.
+ * @throws OperationFailedException with the corresponding code if we fail
+ * to create the video call.
+ * @throws ParseException if <tt>callee</tt> is not a valid sip address
+ * string.
+ */
+ public Call createVideoCall(String uri, QualityPresets qualityPreferences)
+ throws OperationFailedException, ParseException
+ {
Address toAddress = parentProvider.parseAddressString(uri);
CallSipImpl call = basicTelephony.createOutgoingCall();
call.setLocalVideoAllowed(true, getMediaUseCase());
+ call.setInitialQualityPreferences(qualityPreferences);
call.invite(toAddress, null);
return call;
@@ -113,6 +158,10 @@ public class OperationSetVideoTelephonySipImpl
*
* @param callee the address of the callee that we should invite to a new
* call.
+ * @param qualityPreferences the quality preset we will use establishing
+ * the video call, and we will expect from the other side. When establishing
+ * call we don't have any indications whether remote part supports quality
+ * presets, so this setting can be ignored.
* @return CallPeer the CallPeer that will represented by the
* specified uri. All following state change events will be delivered
* through that call peer. The Call that this peer is a member
@@ -121,7 +170,9 @@ public class OperationSetVideoTelephonySipImpl
* @throws OperationFailedException with the corresponding code if we fail
* to create the video call.
*/
- public Call createVideoCall(Contact callee) throws OperationFailedException
+ public Call createVideoCall(Contact callee,
+ QualityPresets qualityPreferences)
+ throws OperationFailedException
{
Address toAddress;
@@ -138,6 +189,7 @@ public class OperationSetVideoTelephonySipImpl
CallSipImpl call = basicTelephony.createOutgoingCall();
call.setLocalVideoAllowed(true, getMediaUseCase());
+ call.setInitialQualityPreferences(qualityPreferences);
call.invite(toAddress, null);
return call;
@@ -162,19 +214,12 @@ public class OperationSetVideoTelephonySipImpl
}
/**
- * Changes the current video settings for the peer with the desired
- * quality settings and inform the peer to stream the video
- * with those settings.
- *
- * @param peer the peer that is sending us the video
- * @param preset the desired video settings
- * @throws OperationFailedException
+ * Returns the quality control for video calls if any.
+ * @param peer the peer which this control operates on.
+ * @return the implemented quality control.
*/
- public void setQualityPreset(CallPeer peer,
- QualityPreset preset)
- throws OperationFailedException
+ public QualityControls getQualityControls(CallPeer peer)
{
- CallPeerSipImpl sipPeer = (CallPeerSipImpl) peer;
- sipPeer.setVideoQualityPreset(preset);
+ return ((CallPeerSipImpl) peer).getMediaHandler().getQualityControls();
}
}
diff --git a/src/net/java/sip/communicator/impl/protocol/sip/QualityControlsWrapper.java b/src/net/java/sip/communicator/impl/protocol/sip/QualityControlsWrapper.java
new file mode 100644
index 0000000..0bb1f87
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/protocol/sip/QualityControlsWrapper.java
@@ -0,0 +1,180 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.protocol.sip;
+
+import net.java.sip.communicator.service.neomedia.*;
+import net.java.sip.communicator.service.protocol.*;
+import net.java.sip.communicator.util.*;
+
+/**
+ * A wrapper of media quality control.
+ * @author Damian Minkov
+ */
+public class QualityControlsWrapper
+ implements QualityControls
+{
+ /**
+ * Our class logger.
+ */
+ private static final Logger logger
+ = Logger.getLogger(QualityControlsWrapper.class);
+
+ /**
+ * The peer we are controlling.
+ */
+ private CallPeerSipImpl peer;
+
+ /**
+ * The media quality control.
+ */
+ private QualityControls qualityControls;
+
+ /**
+ * The currently used video quality preset.
+ */
+ protected QualityPresets remoteSendMaxPreset = null;
+
+ /**
+ * The frame rate.
+ */
+ private float maxFrameRate = -1;
+
+ /**
+ * Creates quality control for peer.
+ * @param peer
+ */
+ QualityControlsWrapper(CallPeerSipImpl peer)
+ {
+ this.peer = peer;
+ }
+
+ /**
+ * Checks and obtains quality control from media stream.
+ * @return
+ */
+ private QualityControls getMediaQualityControls()
+ {
+ if(qualityControls != null)
+ return qualityControls;
+
+ MediaStream stream = peer.getMediaHandler().getStream(MediaType.VIDEO);
+
+ if(stream != null && stream instanceof VideoMediaStream)
+ qualityControls = ((VideoMediaStream)stream).getQualityControls();
+
+ return qualityControls;
+ }
+
+ /**
+ * The currently used quality preset announced as receive by remote party.
+ * @return the current quality preset.
+ */
+ public QualityPresets getRemoteReceivePreset()
+ {
+ QualityControls qControls = getMediaQualityControls();
+
+ if(qControls == null)
+ {
+ return null;
+ }
+
+ return qControls.getRemoteReceivePreset();
+ }
+
+ /**
+ * The minimum preset that the remote party is sending and we are receiving.
+ * Not Used.
+ * @return the minimum remote preset.
+ */
+ public QualityPresets getRemoteSendMinPreset()
+ {
+ QualityControls qControls = getMediaQualityControls();
+
+ if(qControls == null)
+ return null;
+
+ return qControls.getRemoteSendMinPreset();
+ }
+
+ /**
+ * The maximum preset that the remote party is sending and we are receiving.
+ * @return the maximum preset announced from remote party as send.
+ */
+ public QualityPresets getRemoteSendMaxPreset()
+ {
+ QualityControls qControls = getMediaQualityControls();
+
+ if(qControls == null)
+ return remoteSendMaxPreset;
+
+ QualityPresets qp = qControls.getRemoteSendMaxPreset();
+
+ // there is info about max frame rate
+ if(qp != null && maxFrameRate > 0)
+ qp = new QualityPresets(qp.getResolution(), (int)maxFrameRate);
+
+ return qp;
+ }
+
+ /**
+ * Changes local value of frame rate, the one we have received from
+ * remote party.
+ * @param f new frame rate.
+ */
+ public void setMaxFrameRate(float f)
+ {
+ this.maxFrameRate = f;
+ }
+
+ /**
+ * Changes remote send preset. This doesn't have impact of current stream.
+ * But will have on next media changes.
+ * With this we can try to change the resolution that the remote part
+ * is sending.
+ * @param preset the new preset value.
+ */
+ public void setRemoteSendMaxPreset(QualityPresets preset)
+ {
+ QualityControls qControls = getMediaQualityControls();
+
+ if(qControls != null)
+ qControls.setRemoteSendMaxPreset(preset);
+ else
+ remoteSendMaxPreset = preset;
+ }
+
+ /**
+ * Changes the current video settings for the peer with the desired
+ * quality settings and inform the peer to stream the video
+ * with those settings.
+ *
+ * @param preset the desired video settings
+ * @throws OperationFailedException
+ */
+ public void setPreferredRemoteSendMaxPreset(QualityPresets preset)
+ throws OperationFailedException
+ {
+ QualityControls qControls = getMediaQualityControls();
+
+ if(qControls != null)
+ {
+ qControls.setRemoteSendMaxPreset(preset);
+
+ try
+ {
+ // re-invites the peer with the new settings
+ peer.sendReInvite();
+ }
+ catch (Throwable ex)
+ {
+ ProtocolProviderServiceSipImpl.throwOperationFailedException(
+ "Failed to re-invite for video quality change.",
+ OperationFailedException.INTERNAL_ERROR, ex, logger);
+ }
+ }
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/protocol/sip/sdp/SdpUtils.java b/src/net/java/sip/communicator/impl/protocol/sip/sdp/SdpUtils.java
index 9d58df6..45a3c05 100644
--- a/src/net/java/sip/communicator/impl/protocol/sip/sdp/SdpUtils.java
+++ b/src/net/java/sip/communicator/impl/protocol/sip/sdp/SdpUtils.java
@@ -372,7 +372,7 @@ public class SdpUtils
{
String frStr = mediaDesc.getAttribute("framerate");
if(frStr != null)
- frameRate = Integer.parseInt(frStr);
+ frameRate = Float.parseFloat(frStr);
}
catch(SdpParseException e)
{
@@ -1532,6 +1532,42 @@ public class SdpUtils
}
/**
+ * Returns the media type (e.g. audio or video) for the specified media
+ * whether it contains the specified <tt>attributeName</tt>.
+ *
+ * @param description the <tt>MediaDescription</tt> whose media type we'd
+ * like to extract.
+ *
+ * @return the media type (e.g. audio or video) for the specified media
+ * <tt>description</tt>.
+ *
+ * @throws IllegalArgumentException if <tt>description</tt> does not
+ * contain a known media type.
+ */
+ public static boolean containsAttribute(MediaDescription description,
+ String attributeName)
+ throws IllegalArgumentException
+ {
+ try
+ {
+ Vector<Attribute> atts = description.getAttributes(false);
+ for(Attribute a : atts)
+ if(a.getName().equals(attributeName))
+ return true;
+
+ return false;
+ }
+ catch (SdpException exc)
+ {
+ // impossible to happen for reasons mentioned many times here :)
+ if (logger.isDebugEnabled())
+ logger.debug("Invalid media type in a= line: " + description, exc);
+ throw new IllegalArgumentException(
+ "Invalid media type in a= line: " + description, exc);
+ }
+ }
+
+ /**
* Creates and returns a <tt>MediaDescription</tt> in answer of the
* specified <tt>offer</tt> that disables the corresponding stream by
* setting a <tt>0</tt> port and keeping the original list of formats and
diff --git a/src/net/java/sip/communicator/service/neomedia/QualityControls.java b/src/net/java/sip/communicator/service/neomedia/QualityControls.java
new file mode 100644
index 0000000..78bfe10
--- /dev/null
+++ b/src/net/java/sip/communicator/service/neomedia/QualityControls.java
@@ -0,0 +1,53 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.service.neomedia;
+
+import net.java.sip.communicator.service.protocol.*;
+
+/**
+ * The quality controls we use to control other party video presets.
+ * @author Damian Minkov
+ */
+public interface QualityControls
+{
+ /**
+ * The currently used quality preset announced as receive by remote party.
+ * @return the current quality preset.
+ */
+ public QualityPresets getRemoteReceivePreset();
+
+ /**
+ * The minimum preset that the remote party is sending and we are receiving.
+ * @return the minimum remote preset.
+ */
+ public QualityPresets getRemoteSendMinPreset();
+
+ /**
+ * The maximum preset that the remote party is sending and we are receiving.
+ * @return the maximum preset announced from remote party as send.
+ */
+ public QualityPresets getRemoteSendMaxPreset();
+
+ /**
+ * Changes remote send preset. This doesn't have impact of current stream.
+ * But will have on next media changes.
+ * With this we can try to change the resolution that the remote part
+ * is sending.
+ * @param preset the new preset value.
+ */
+ public void setRemoteSendMaxPreset(QualityPresets preset);
+
+ /**
+ * Changes remote send preset and protocols who can handle the changes
+ * will implement this for re-inviting the other party or just sending that
+ * media has changed.
+ * @param preset the new preset.
+ * @throws OperationFailedException
+ */
+ public void setPreferredRemoteSendMaxPreset(QualityPresets preset)
+ throws OperationFailedException;
+}
diff --git a/src/net/java/sip/communicator/service/neomedia/QualityPreset.java b/src/net/java/sip/communicator/service/neomedia/QualityPreset.java
deleted file mode 100644
index 9aba5ba..0000000
--- a/src/net/java/sip/communicator/service/neomedia/QualityPreset.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package net.java.sip.communicator.service.neomedia;
-
-import java.awt.*;
-
-/**
- * Predefined Quality presets used to specify some video settings during
- * call or when starting call.
- * @author Damian Minkov
- */
-public class QualityPreset
-{
- /**
- * 720p HD
- */
- public final static QualityPreset HD_QUALITY =
- new QualityPreset(new Dimension(1280, 720), 30);
-
- /**
- * SD
- */
- public final static QualityPreset SD_QUALITY =
- new QualityPreset(new Dimension(640, 480), 20);
-
- /**
- * Low
- */
- public final static QualityPreset LO_QUALITY =
- new QualityPreset(new Dimension(320, 240), 15);
-
- /**
- * The frame rate to use.
- */
- private int frameRate;
-
- /**
- * The resolution to use.
- */
- private Dimension resolution;
-
- /**
- * Creates preset with <tt>resolution</tt> and <tt>frameRate</tt>.
- * Predefined presets can be created only here.
- *
- * @param resolution the resolution.
- * @param frameRate the frame rate.
- */
- private QualityPreset(Dimension resolution, int frameRate)
- {
- this.frameRate = frameRate;
- this.resolution = resolution;
- }
-
- /**
- * Returns this preset frame rate.
- * @return the frame rate.
- */
- public int getFameRate()
- {
- return this.frameRate;
- }
-
- /**
- * Returns this preset resolution.
- * @return the resolution.
- */
- public Dimension getResolution()
- {
- return this.resolution;
- }
-}
diff --git a/src/net/java/sip/communicator/service/neomedia/QualityPresets.java b/src/net/java/sip/communicator/service/neomedia/QualityPresets.java
new file mode 100644
index 0000000..02a047a
--- /dev/null
+++ b/src/net/java/sip/communicator/service/neomedia/QualityPresets.java
@@ -0,0 +1,106 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.service.neomedia;
+
+import java.awt.*;
+
+/**
+ * Predefined Quality presets used to specify some video settings during
+ * call or when starting call.
+ * @author Damian Minkov
+ */
+public class QualityPresets
+ implements Comparable<QualityPresets>
+{
+ /**
+ * 720p HD
+ */
+ public final static QualityPresets HD_QUALITY =
+ new QualityPresets(new Dimension(1280, 720), 30);
+
+ /**
+ * SD
+ */
+ public final static QualityPresets SD_QUALITY =
+ new QualityPresets(new Dimension(640, 480), 20);
+
+ /**
+ * Low
+ */
+ public final static QualityPresets LO_QUALITY =
+ new QualityPresets(new Dimension(320, 240), 15);
+
+ /**
+ * The frame rate to use.
+ */
+ private float frameRate;
+
+ /**
+ * The resolution to use.
+ */
+ private Dimension resolution;
+
+ /**
+ * Creates preset with <tt>resolution</tt> and <tt>frameRate</tt>.
+ * Predefined presets can be created only here.
+ *
+ * @param resolution the resolution.
+ * @param frameRate the frame rate.
+ */
+ public QualityPresets(Dimension resolution, float frameRate)
+ {
+ this.frameRate = frameRate;
+ this.resolution = resolution;
+ }
+
+ /**
+ * Creates preset with <tt>resolution</tt> and <tt>frameRate</tt>.
+ * Predefined presets can be created only here.
+ *
+ * @param resolution the resolution.
+ */
+ public QualityPresets(Dimension resolution)
+ {
+ // unspecified frame rate
+ this(resolution, -1);
+ }
+
+ /**
+ * Returns this preset frame rate.
+ * @return the frame rate.
+ */
+ public float getFameRate()
+ {
+ return this.frameRate;
+ }
+
+ /**
+ * Returns this preset resolution.
+ * @return the resolution.
+ */
+ public Dimension getResolution()
+ {
+ return this.resolution;
+ }
+
+ /**
+ * Compares to presets and its dimensions.
+ * @param o object to compare to.
+ * @return a negative integer, zero, or a positive integer as this object is
+ * less than, equal to, or greater than the specified object.
+ */
+ public int compareTo(QualityPresets o)
+ {
+ if(this.resolution.equals(o.resolution))
+ return 0;
+ else if(this.resolution.height < o.resolution.height &&
+ this.resolution.width < o.resolution.width)
+ return -1;
+ else
+ return 1;
+ }
+}
diff --git a/src/net/java/sip/communicator/service/neomedia/VideoMediaStream.java b/src/net/java/sip/communicator/service/neomedia/VideoMediaStream.java
index 3e6a320..3ec1235 100644
--- a/src/net/java/sip/communicator/service/neomedia/VideoMediaStream.java
+++ b/src/net/java/sip/communicator/service/neomedia/VideoMediaStream.java
@@ -73,4 +73,10 @@ public interface VideoMediaStream
* <tt>VideoMediaStream</tt>
*/
public void removeVideoListener(VideoListener listener);
+
+ /**
+ * The quality control that can be used with this stream.
+ * @return the quality control.
+ */
+ public QualityControls getQualityControls();
}
diff --git a/src/net/java/sip/communicator/service/neomedia/device/MediaDevice.java b/src/net/java/sip/communicator/service/neomedia/device/MediaDevice.java
index ef5233a..f43705a 100644
--- a/src/net/java/sip/communicator/service/neomedia/device/MediaDevice.java
+++ b/src/net/java/sip/communicator/service/neomedia/device/MediaDevice.java
@@ -32,11 +32,15 @@ public interface MediaDevice
* Returns a list of <tt>MediaFormat</tt> instances representing the media
* formats supported by this <tt>MediaDevice</tt>.
*
- * @param preset the preset used to set some of the format parameters,
+ * @param localPreset the preset used to set the send format parameters,
* used for video and settings.
+ * @param remotePreset the preset used to set the receive format parameters,
+ * used for video and settings.
+ *
* @return the list of <tt>MediaFormat</tt>s supported by this device.
*/
- public List<MediaFormat> getSupportedFormats(QualityPreset preset);
+ public List<MediaFormat> getSupportedFormats(QualityPresets localPreset,
+ QualityPresets remotePreset);
/**
* Returns the <tt>List</tt> of <tt>RTPExtension</tt>s that this device
diff --git a/src/net/java/sip/communicator/service/protocol/OperationSetVideoTelephony.java b/src/net/java/sip/communicator/service/protocol/OperationSetVideoTelephony.java
index 08488b1..cc5a988 100644
--- a/src/net/java/sip/communicator/service/protocol/OperationSetVideoTelephony.java
+++ b/src/net/java/sip/communicator/service/protocol/OperationSetVideoTelephony.java
@@ -216,6 +216,49 @@ public interface OperationSetVideoTelephony
throws OperationFailedException;
/**
+ * Create a new video call and invite the specified CallPeer to it.
+ *
+ * @param uri the address of the callee that we should invite to a new
+ * call.
+ * @param qualityPreferences the quality preset we will use establishing
+ * the video call, and we will expect from the other side. When establishing
+ * call we don't have any indications whether remote part supports quality
+ * presets, so this setting can be ignored.
+ * @return CallPeer the CallPeer that will represented by the
+ * specified uri. All following state change events will be delivered
+ * through that call peer. The Call that this peer is a member
+ * of could be retrieved from the CallParticipatn instance with the use
+ * of the corresponding method.
+ * @throws OperationFailedException with the corresponding code if we fail
+ * to create the video call.
+ * @throws ParseException if <tt>callee</tt> is not a valid sip address
+ * string.
+ */
+ public Call createVideoCall(String uri, QualityPresets qualityPreferences)
+ throws OperationFailedException, ParseException;
+
+ /**
+ * Create a new video call and invite the specified CallPeer to it.
+ *
+ * @param callee the address of the callee that we should invite to a new
+ * call.
+ * @param qualityPreferences the quality preset we will use establishing
+ * the video call, and we will expect from the other side. When establishing
+ * call we don't have any indications whether remote part supports quality
+ * presets, so this setting can be ignored.
+ * @return CallPeer the CallPeer that will represented by the
+ * specified uri. All following state change events will be delivered
+ * through that call peer. The Call that this peer is a member
+ * of could be retrieved from the CallParticipatn instance with the use
+ * of the corresponding method.
+ * @throws OperationFailedException with the corresponding code if we fail
+ * to create the video call.
+ */
+ public Call createVideoCall(Contact callee,
+ QualityPresets qualityPreferences)
+ throws OperationFailedException;
+
+ /**
* Indicates a user request to answer an incoming call with video enabled
* from the specified CallPeer.
* @param peer the call peer that we'd like to answer.
@@ -226,15 +269,10 @@ public interface OperationSetVideoTelephony
throws OperationFailedException;
/**
- * Changes the current video settings for the peer with the desired
- * quality settings and inform the peer to stream the video
- * with those settings.
- *
- * @param peer the peer that is sending us the video
- * @param preset the desired video settings
- * @throws OperationFailedException
+ * Returns the quality control for video calls if any. It can be null if we
+ * were able to successfully determine that other party does not support it.
+ * @param peer the peer which this control operates on.
+ * @return the implemented quality control.
*/
- public void setQualityPreset(CallPeer peer,
- QualityPreset preset)
- throws OperationFailedException;
+ public QualityControls getQualityControls(CallPeer peer);
}
diff --git a/src/net/java/sip/communicator/service/protocol/media/AbstractOperationSetVideoTelephony.java b/src/net/java/sip/communicator/service/protocol/media/AbstractOperationSetVideoTelephony.java
index f2693fb..593aae0 100644
--- a/src/net/java/sip/communicator/service/protocol/media/AbstractOperationSetVideoTelephony.java
+++ b/src/net/java/sip/communicator/service/protocol/media/AbstractOperationSetVideoTelephony.java
@@ -8,6 +8,7 @@ package net.java.sip.communicator.service.protocol.media;
import java.awt.*;
import java.beans.*;
+import java.text.*;
import net.java.sip.communicator.service.neomedia.*;
import net.java.sip.communicator.service.protocol.*;
@@ -260,18 +261,67 @@ public abstract class AbstractOperationSetVideoTelephony<
}
/**
- * Changes the current video settings for the peer with the desired
- * quality settings and inform the peer to stream the video
- * with those settings.
+ * Returns the quality control for video calls if any.
+ * Return null so protocols who supports it to override it.
+ * @param peer the peer which this control operates on.
+ * @return the implemented quality control.
+ */
+ public QualityControls getQualityControls(CallPeer peer)
+ {
+ return null;
+ }
+
+ /**
+ * Create a new video call and invite the specified CallPeer to it with
+ * initial video setting.
*
- * @param peer the peer that is sending us the video
- * @param preset the desired video settings
- * @throws OperationFailedException
+ * @param uri the address of the callee that we should invite to a new
+ * call.
+ * @param qualityPreferences the quality preset we will use establishing
+ * the video call, and we will expect from the other side. When establishing
+ * call we don't have any indications whether remote part supports quality
+ * presets, so this setting can be ignored.
+ * @return CallPeer the CallPeer that will represented by the
+ * specified uri. All following state change events will be delivered
+ * through that call peer. The Call that this peer is a member
+ * of could be retrieved from the CallParticipatn instance with the use
+ * of the corresponding method.
+ * @throws OperationFailedException with the corresponding code if we fail
+ * to create the video call.
+ * @throws java.text.ParseException if <tt>callee</tt> is not a valid sip address
+ * string.
*/
- public void setQualityPreset(CallPeer peer,
- QualityPreset preset)
+ public Call createVideoCall(String uri, QualityPresets qualityPreferences)
+ throws OperationFailedException,
+ ParseException
+ {
+ return createVideoCall(uri);
+ }
+
+ /**
+ * Create a new video call and invite the specified CallPeer to it with
+ * initial video setting.
+ *
+ * @param callee the address of the callee that we should invite to a new
+ * call.
+ * @param qualityPreferences the quality preset we will use establishing
+ * the video call, and we will expect from the other side. When establishing
+ * call we don't have any indications whether remote part supports quality
+ * presets, so this setting can be ignored.
+ * @return CallPeer the CallPeer that will represented by the
+ * specified uri. All following state change events will be delivered
+ * through that call peer. The Call that this peer is a member
+ * of could be retrieved from the CallParticipatn instance with the use
+ * of the corresponding method.
+ * @throws OperationFailedException with the corresponding code if we fail
+ * to create the video call.
+ */
+ public Call createVideoCall(Contact callee,
+ QualityPresets qualityPreferences)
throws OperationFailedException
- {}
+ {
+ return createVideoCall(callee);
+ }
/**
* Represents a <tt>VideoListener</tt> which forwards notifications to a
diff --git a/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java b/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java
index 9b64120..65287a8 100644
--- a/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java
+++ b/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java
@@ -204,11 +204,6 @@ public abstract class CallPeerMediaHandler<
= new LinkedList<VideoListener>();
/**
- * The currently used video quality preset.
- */
- protected QualityPreset videoQualityPreset = null;
-
- /**
* The <tt>PropertyChangeListener</tt> which listens to changes in the
* values of the properties of {@link #audioStream} and
* {@link #videoStream}.
@@ -1612,15 +1607,6 @@ public abstract class CallPeerMediaHandler<
}
/**
- * Changes video quality preset.
- * @param preset the preset to use.
- */
- public void setVideoQualityPreset(QualityPreset preset)
- {
- this.videoQualityPreset = preset;
- }
-
- /**
* Lets the underlying implementation take note of this error and only
* then throws it to the using bundles.
*