Allow setting params for the size of image we are able to show during video call and dispatch such params by streaming the supplied resolution.

cusax-fix
Damian Minkov 15 years ago
parent 2883ad8973
commit 926eb21784

@ -815,6 +815,7 @@ public void actionPerformed(ActionEvent e)
sizeCombo.setSelectedIndex(0);
frameRateCheck.setSelected(false);
frameRate.setEnabled(false);
frameRate.setValue(20);
// unlimited framerate
deviceConfig.setFrameRate(-1);
videoMaxBandwidth.setValue(

@ -607,7 +607,7 @@ else if (jmfEncoding.equals(VideoFormat.H261_RTP))
* @return string that represent imgattr that can be encoded via SIP/SDP or
* XMPP/Jingle
*/
private static String createImageAttr(java.awt.Dimension sendSize,
public static String createImageAttr(java.awt.Dimension sendSize,
java.awt.Dimension maxRecvSize)
{
StringBuffer img = new StringBuffer();

@ -162,9 +162,8 @@ public int compare(FormatInfo info0, FormatInfo info1)
}
/*
* If videoDS states to support any size, use the default size
* because we don't know anything about the correctness of the
* preferred size.
* If videoDS states to support any size, use the sizes that we
* support which is closest(or smaller) to the preferred one.
*/
if ((selectedFormat != null)
&& (selectedFormat.getSize() == null))
@ -178,26 +177,29 @@ public int compare(FormatInfo info0, FormatInfo info1)
// Try to preserve the aspect ratio
if (currentFormat != null)
currentSize = currentFormat.getSize();
if (currentSize == null)
currentSize
= NeomediaActivator
.getMediaServiceImpl()
.getDeviceConfiguration()
.getVideoSize();
// lets choose the closest size to the preferred one
for(Dimension supported :
DeviceConfiguration.SUPPORTED_RESOLUTIONS)
{
if(supported.height <= preferredHeight
&& supported.width <= preferredWidth)
currentSize = supported;
}
if ((currentSize.width > 0) && (currentSize.height > 0))
{
width = currentSize.width;
height = currentSize.height;
}
selectedFormat
= (VideoFormat)
selectedFormat.intersects(
new VideoFormat(
= (VideoFormat)new VideoFormat(
null,
new Dimension(width, height),
Format.NOT_SPECIFIED,
null,
Format.NOT_SPECIFIED));
Format.NOT_SPECIFIED)
.intersects(selectedFormat);
}
}

@ -412,6 +412,17 @@ public List<RTPExtension> getSupportedExtensions()
return rtpExtensions;
}
/**
* Gets a list of <tt>MediaFormat</tt>s supported by this
* <tt>MediaDevice</tt>. Currently does nothing.
* @param preset 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)
{
return device.getSupportedFormats();
}
/**
* Gets a list of <tt>MediaFormat</tt>s supported by this
* <tt>MediaDevice</tt>.
@ -421,7 +432,7 @@ public List<RTPExtension> getSupportedExtensions()
*/
public List<MediaFormat> getSupportedFormats()
{
return device.getSupportedFormats();
return this.getSupportedFormats(null);
}
/**

@ -322,6 +322,18 @@ public MediaType getMediaType()
* @see MediaDevice#getSupportedFormats()
*/
public List<MediaFormat> getSupportedFormats()
{
return this.getSupportedFormats(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,
* 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)
{
EncodingConfiguration encodingConfiguration
= NeomediaActivator
@ -334,6 +346,42 @@ public List<MediaFormat> getSupportedFormats()
for (MediaFormat supportedEncoding : supportedEncodings)
supportedFormats.add(supportedEncoding);
// if there is preset check and set the format attributes
// where needed
if(preset != null)
{
MediaFormat customFormat = null;
MediaFormat toRemove = null;
for(MediaFormat f : supportedFormats)
{
if("h264".equalsIgnoreCase(f.getEncoding()))
{
Map<String,String> h264AdvancedAttributes =
f.getAdvancedAttributes();
if(h264AdvancedAttributes == null)
h264AdvancedAttributes = new HashMap<String, String>();
h264AdvancedAttributes.put("imageattr",
MediaUtils.createImageAttr(null,
preset.getResolution()));
customFormat = NeomediaActivator.getMediaServiceImpl()
.getFormatFactory().createMediaFormat(
f.getEncoding(),
f.getClockRate(),
f.getFormatParameters(),
h264AdvancedAttributes);
toRemove = f;
}
}
if(toRemove != null && customFormat != null)
{
supportedFormats.remove(toRemove);
supportedFormats.add(customFormat);
}
}
return supportedFormats;
}

@ -178,6 +178,12 @@ public class MediaDeviceSession
*/
private boolean disposePlayerWhenClose = true;
/**
* Whether output size has changed after latest processor config.
* Used for video streams.
*/
protected boolean outputsizeChanged = false;
/**
* Initializes a new <tt>MediaDeviceSession</tt> instance which is to
* represent the use of a specific <tt>MediaDevice</tt> by a
@ -1336,8 +1342,10 @@ public void setFormat(MediaFormat format)
else if (processorIsPrematurelyClosed
|| ((processorState > Processor.Configured)
&& !this.format.getFormat().equals(
getProcessorFormat())))
getProcessorFormat()))
|| outputsizeChanged)
{
outputsizeChanged = false;
setProcessor(null);
}
}

@ -22,6 +22,7 @@
import net.java.sip.communicator.impl.neomedia.transform.*;
import net.java.sip.communicator.service.neomedia.*;
import net.java.sip.communicator.service.neomedia.event.*;
import net.java.sip.communicator.service.neomedia.format.*;
import net.java.sip.communicator.service.resources.*;
import net.java.sip.communicator.util.*;
@ -186,6 +187,13 @@ protected DataSource createCaptureDevice()
{
Dimension videoSize = deviceConfig.getVideoSize();
// if we have an output size that is smaller than our current
// settings, respect that size
if(outputSize != null
&& videoSize.height > outputSize.height
&& videoSize.width > outputSize.width)
videoSize = outputSize;
VideoMediaStreamImpl.selectVideoSize(
captureDevice,
videoSize.width, videoSize.height);
@ -1103,6 +1111,11 @@ public void setRtcpFeedbackPLI(boolean use)
*/
public void setOutputSize(Dimension size)
{
if((size != null && outputSize == null)
|| (size == null && outputSize != null)
|| (size != null && outputSize != null && !outputSize.equals(size)))
outputsizeChanged = true;
outputSize = size;
}
@ -1300,6 +1313,43 @@ protected Format setProcessorFormat(
return super.setProcessorFormat(trackControl, mediaFormat, format);
}
/**
* Sets the <tt>MediaFormat</tt> in which this <tt>MediaDeviceSession</tt>
* outputs the media captured by its <tt>MediaDevice</tt>.
*
* @param format the <tt>MediaFormat</tt> in which this
* <tt>MediaDeviceSession</tt> is to output the media captured by its
* <tt>MediaDevice</tt>
*/
public void setFormat(MediaFormat format)
{
if(format instanceof VideoMediaFormat &&
((VideoMediaFormat)format).getFrameRate() != -1)
{
FrameRateControl frameRateControl
= (FrameRateControl)
getCaptureDevice().getControl(FrameRateControl.class.getName());
if (frameRateControl != null)
{
float frameRate = ((VideoMediaFormat)format).getFrameRate();
float maxSupportedFrameRate
= frameRateControl.getMaxSupportedFrameRate();
if ((maxSupportedFrameRate > 0)
&& (frameRate > maxSupportedFrameRate))
frameRate = maxSupportedFrameRate;
if(frameRate > 0)
{
frameRateControl.setFrameRate(frameRate);
}
}
}
super.setFormat(format);
}
/**
* Notifies this instance that the value of its <tt>startedDirection</tt>
* property has changed from a specific <tt>oldValue</tt> to a specific

@ -209,7 +209,7 @@ public MediaFormat createMediaFormat(
{
return
createMediaFormat(
encoding, clockRate, 1,
encoding, clockRate, 1, -1,
formatParams,
advancedParams);
}
@ -225,6 +225,8 @@ public MediaFormat createMediaFormat(
* <tt>MediaFormat</tt> for
* @param clockRate the clock rate in Hz to create a <tt>MediaFormat</tt>
* for
* @param frameRate the frame rate in number of frames per second to
* create a <tt>MediaFormat</tt> for
* @param channels the number of available channels (1 for mono, 2 for
* stereo) if it makes sense for the <tt>MediaFormat</tt> with the specified
* <tt>encoding</tt>; otherwise, ignored
@ -237,10 +239,10 @@ public MediaFormat createMediaFormat(
* is either an <tt>AudioMediaFormat</tt> or a <tt>VideoMediaFormat</tt>
* instance if <tt>encoding</tt> is known to this
* <tt>MediaFormatFactory</tt>; otherwise, <tt>null</tt>
* @see MediaFormatFactory#createMediaFormat(String, double, int, Map, Map)
* @see MediaFormatFactory#createMediaFormat(String, double, int, float, Map, Map)
*/
public MediaFormat createMediaFormat(
String encoding, double clockRate, int channels,
String encoding, double clockRate, int channels, float frameRate,
Map<String, String> formatParams,
Map<String, String> advancedParams)
{
@ -293,6 +295,7 @@ public MediaFormat createMediaFormat(
= new VideoMediaFormatImpl(
videoMediaFormatImpl.getFormat(),
videoMediaFormatImpl.getClockRate(),
frameRate,
formatParameters, advancedParameters);
break;
default:
@ -322,6 +325,8 @@ public MediaFormat createMediaFormat(
* <tt>MediaFormat</tt> for; <tt>null</tt>
* @param clockRate the clock rate in Hz to create a <tt>MediaFormat</tt>
* for
* @param frameRate the frame rate in number of frames per second to
* create a <tt>MediaFormat</tt> for
* @param channels the number of available channels (1 for mono, 2 for
* stereo) if it makes sense for the <tt>MediaFormat</tt> with the specified
* <tt>encoding</tt>; otherwise, ignored
@ -337,7 +342,7 @@ public MediaFormat createMediaFormat(
*/
public MediaFormat createMediaFormat(
byte rtpPayloadType,
String encoding, double clockRate, int channels,
String encoding, double clockRate, int channels, float frameRate,
Map<String, String> formatParams,
Map<String, String> advancedParams)
{
@ -384,7 +389,7 @@ public MediaFormat createMediaFormat(
return
createMediaFormat(
encoding, clockRate, channels,
encoding, clockRate, channels, frameRate,
formatParams,
advancedParams);
}

@ -101,6 +101,7 @@ public static MediaFormatImpl<? extends Format> createInstance(
new VideoMediaFormatImpl(
(VideoFormat) format,
clockRate,
-1,
formatParameters,
advancedAttrs);
return null;

@ -35,6 +35,11 @@ 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.
@ -86,7 +91,7 @@ public class VideoMediaFormatImpl
*/
VideoMediaFormatImpl(VideoFormat format, double clockRate)
{
this(format, clockRate, null, null);
this(format, clockRate, -1, null, null);
}
/**
@ -99,6 +104,8 @@ public class VideoMediaFormatImpl
* and provide an implementation of <tt>VideoMediaFormat</tt> for
* @param clockRate the clock rate of the new <tt>VideoMediaFormatImpl</tt>
* instance
* @param frameRate the frame rate of the new <tt>VideoMediaFormatImpl</tt>
* instance
* @param formatParameters the set of format-specific parameters of the new
* instance
* @param advancedParameters set of advanced parameters of the new instance
@ -106,12 +113,14 @@ public class VideoMediaFormatImpl
VideoMediaFormatImpl(
VideoFormat format,
double clockRate,
float frameRate,
Map<String, String> formatParameters,
Map<String, String> advancedParameters)
{
super(format, formatParameters, advancedParameters);
this.clockRate = clockRate;
this.frameRate = frameRate;
}
/**
@ -243,6 +252,17 @@ public double getClockRate()
return clockRate;
}
/**
* Gets the frame rate associated with this <tt>MediaFormat</tt>.
*
* @return the frame rate associated with this <tt>MediaFormat</tt>
* @see VideoMediaFormat#getFrameRate()
*/
public float getFrameRate()
{
return frameRate;
}
/**
* Gets the type of this <tt>MediaFormat</tt> which is
* {@link MediaType#VIDEO} for <tt>AudioMediaFormatImpl</tt> instances.

@ -132,6 +132,7 @@ public static MediaFormat payloadTypeToMediaFormat(
pt,
payloadType.getName(),
(double)payloadType.getClockrate(),
-1,
payloadType.getChannels(),
paramsMap,
null);

@ -166,11 +166,25 @@ private Vector<MediaDescription> createMediaDescriptions()
{
MediaDescription md =
createMediaDescription(
dev.getSupportedFormats(),
dev.getSupportedFormats(videoQualityPreset),
getTransportManager().getStreamConnector(mediaType),
direction,
dev.getSupportedExtensions());
try
{
// if we have setting for video preset lets
// send info for the desired framerate
if(videoQualityPreset != null)
md.setAttribute("framerate",
String.valueOf(
videoQualityPreset.getFameRate()));
}
catch(SdpException e)
{
// do nothing in case of error.
}
updateMediaDescriptionForZrtp(mediaType, md);
mediaDescs.add(md);

@ -16,6 +16,7 @@
import javax.sip.message.*;
import net.java.sip.communicator.impl.protocol.sip.sdp.*;
import net.java.sip.communicator.service.neomedia.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.service.protocol.media.*;
@ -1355,4 +1356,29 @@ private void setDisconnectedState(boolean failed, String reason)
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);
}
}
}

@ -10,6 +10,7 @@
import javax.sip.address.Address;
import net.java.sip.communicator.service.neomedia.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.media.*;
import net.java.sip.communicator.util.*;
@ -159,4 +160,21 @@ public void answerVideoCallPeer(CallPeer peer)
callPeer.getCall().setLocalVideoAllowed(true, getMediaUseCase());
callPeer.answer();
}
/**
* 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
*/
public void setQualityPreset(CallPeer peer,
QualityPreset preset)
throws OperationFailedException
{
CallPeerSipImpl sipPeer = (CallPeerSipImpl) peer;
sipPeer.setVideoQualityPreset(preset);
}
}

@ -366,6 +366,19 @@ public static List<MediaFormat> extractFormats(
return mediaFmts;
}
float frameRate = -1;
// check for frame rate setting
try
{
String frStr = mediaDesc.getAttribute("framerate");
if(frStr != null)
frameRate = Integer.parseInt(frStr);
}
catch(SdpParseException e)
{
// do nothing
}
for(String ptStr : formatStrings)
{
byte pt = -1;
@ -428,7 +441,8 @@ public static List<MediaFormat> extractFormats(
MediaFormat mediaFormat = null;
try
{
mediaFormat = createFormat(pt, rtpmap, fmtp, advp, ptRegistry);
mediaFormat = createFormat(
pt, rtpmap, fmtp, frameRate, advp, ptRegistry);
}
catch (SdpException e)
{
@ -628,6 +642,7 @@ private static MediaFormat createFormat(
byte payloadType,
Attribute rtpmap,
Attribute fmtp,
float frameRate,
List<Attribute> advp,
DynamicPayloadTypeRegistry ptRegistry)
throws SdpException
@ -713,7 +728,7 @@ private static MediaFormat createFormat(
= SipActivator.getMediaService().getFormatFactory()
.createMediaFormat(
payloadType,
encoding, clockRate, numChannels,
encoding, clockRate, numChannels, frameRate,
fmtParamsMap,
advancedAttrMap);

@ -0,0 +1,76 @@
/*
* 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;
}
}

@ -28,6 +28,16 @@ public interface MediaDevice
*/
public List<MediaFormat> getSupportedFormats();
/**
* 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,
* used for video and settings.
* @return the list of <tt>MediaFormat</tt>s supported by this device.
*/
public List<MediaFormat> getSupportedFormats(QualityPreset preset);
/**
* Returns the <tt>List</tt> of <tt>RTPExtension</tt>s that this device
* know how to handle.

@ -157,6 +157,8 @@ public MediaFormat createMediaFormat(
* <tt>MediaFormat</tt> for
* @param clockRate the clock rate in Hz to create a <tt>MediaFormat</tt>
* for
* @param frameRate the frame rate in number of frames per second to
* create a <tt>MediaFormat</tt> for
* @param channels the number of available channels (1 for mono, 2 for
* stereo) if it makes sense for the <tt>MediaFormat</tt> with the specified
* <tt>encoding</tt>; otherwise, ignored
@ -174,6 +176,7 @@ public MediaFormat createMediaFormat(
String encoding,
double clockRate,
int channels,
float frameRate,
Map<String, String> formatParams,
Map<String, String> advancedAttrs);
@ -197,6 +200,8 @@ public MediaFormat createMediaFormat(
* <tt>MediaFormat</tt> for; <tt>null</tt>
* @param clockRate the clock rate in Hz to create a <tt>MediaFormat</tt>
* for
* @param frameRate the frame rate in number of frames per second to
* create a <tt>MediaFormat</tt> for
* @param channels the number of available channels (1 for mono, 2 for
* stereo) if it makes sense for the <tt>MediaFormat</tt> with the specified
* <tt>encoding</tt>; otherwise, ignored
@ -215,6 +220,7 @@ public MediaFormat createMediaFormat(
String encoding,
double clockRate,
int channels,
float frameRate,
Map<String, String> formatParams,
Map<String, String> advancedAttrs);
}

@ -26,4 +26,11 @@ public interface VideoMediaFormat
* (in pixels) of this <tt>VideoMediaFormat</tt>.
*/
public Dimension getSize();
/**
* Returns the frame rate associated with this <tt>MediaFormat</tt>.
*
* @return The frame rate associated with this format.
*/
public float getFrameRate();
}

@ -10,6 +10,7 @@
import java.beans.*;
import java.text.*;
import net.java.sip.communicator.service.neomedia.*;
import net.java.sip.communicator.service.protocol.event.*;
/**
@ -223,4 +224,17 @@ public Call createVideoCall(Contact callee)
*/
public void answerVideoCallPeer(CallPeer peer)
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
*/
public void setQualityPreset(CallPeer peer,
QualityPreset preset)
throws OperationFailedException;
}

@ -259,6 +259,20 @@ public MediaUseCase getMediaUseCase()
return MediaUseCase.CALL;
}
/**
* 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
*/
public void setQualityPreset(CallPeer peer,
QualityPreset preset)
throws OperationFailedException
{}
/**
* Represents a <tt>VideoListener</tt> which forwards notifications to a
* specific delegate <tt>VideoListener</tt> and hides the original

@ -203,6 +203,11 @@ public abstract class CallPeerMediaHandler<
private final List<VideoListener> videoListeners
= 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
@ -1606,6 +1611,15 @@ public T getPeer()
return peer;
}
/**
* 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.

Loading…
Cancel
Save