Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default simulcast target order can be set with receive-simulcast-layer #179

Merged
merged 4 commits into from Mar 22, 2016
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 5 additions & 1 deletion doc/simulcast.md
Expand Up @@ -157,7 +157,11 @@ the bridge through COLIBRI like this:
</content>

The order of the sources in the simulcast ssrc-group is important and
must be from lowest to highest quality.
must be from lowest to highest quality.

You can specify the default layer with `receive-simulcast-layer` channel
attribute. It accepts an integer and it determines index of layer. The
default is the first layer which is 0.

For simulcast to work you need to use the `BasicBridgeRTCPTerminationStrategy`
RTCP termination strategy. You can configure it like this in you
Expand Down
6 changes: 4 additions & 2 deletions src/main/java/org/jitsi/videobridge/Content.java
Expand Up @@ -255,7 +255,8 @@ void askForKeyframes(Collection<Endpoint> endpoints)
public RtpChannel createRtpChannel(String channelBundleId,
String transportNamespace,
Boolean initiator,
RTPLevelRelayType rtpLevelRelayType)
RTPLevelRelayType rtpLevelRelayType,
Integer receiveSimulcastLayer)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @lluczo, thank you very much for this! 👍

One minor note, I would like to avoid modifying the create createRtpChannel method. Could you please create a setter for the receiveSimulcastLayer parameter in the VideoChannel and use that in Videobridge.java?\

Thank you very much :)

throws Exception
{
RtpChannel channel = null;
Expand Down Expand Up @@ -284,7 +285,8 @@ public RtpChannel createRtpChannel(String channelBundleId,
case VIDEO:
channel = new VideoChannel(
this, id, channelBundleId,
transportNamespace, initiator);
transportNamespace, initiator,
receiveSimulcastLayer);
break;
default:
channel = new RtpChannel(
Expand Down
30 changes: 29 additions & 1 deletion src/main/java/org/jitsi/videobridge/VideoChannel.java
Expand Up @@ -91,6 +91,23 @@ public class VideoChannel
*/
private byte vp8PayloadType = -1;


/**
* XXX Defaulting to the lowest-quality simulcast stream until we are
* explicitly told to switch to a higher-quality simulcast stream is one way
* to go, of course. But such a default presents the problem that a remote
* peer will see the lowest quality possible for a noticeably long period of
* time because its command to switch to the highest quality possible can
* only come via its data/SCTP channel and that may take a very (and
* unpredictably) long time to set up. That is why we may default to the
* highest-quality simulcast stream here.
*
* This value can be set through colibri channel IQ with
* receive-simulcast-layer attribute.
*/
private int receiveSimulcastLayer
= SimulcastStream.SIMULCAST_LAYER_ORDER_BASE; // Integer.MAX_VALUE;

/**
* Updates the values of the property <tt>inLastN</tt> of all
* <tt>VideoChannel</tt>s in the <tt>Content</tt> of a specific
Expand Down Expand Up @@ -179,11 +196,17 @@ public VideoChannel(Content content,
String id,
String channelBundleId,
String transportNamespace,
Boolean initiator)
Boolean initiator,
Integer receiveSimulcastLayer)
throws Exception
{
super(content, id, channelBundleId, transportNamespace, initiator);

if (receiveSimulcastLayer != null)
{
this.receiveSimulcastLayer = receiveSimulcastLayer;
}

setTransformEngine(new RtpChannelTransformEngine(this));

ConfigurationService cfg
Expand Down Expand Up @@ -375,6 +398,11 @@ public int getLastN()
return lastNController.getLastN();
}

public int getReceiveSimulcastLayer()
{
return receiveSimulcastLayer;
}

/**
* Notifies this <tt>VideoChannel</tt> that the value of its property
* <tt>inLastN</tt> has changed from <tt>oldValue</tt> to <tt>newValue</tt>.
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/org/jitsi/videobridge/Videobridge.java
Expand Up @@ -742,7 +742,8 @@ else if (authorizedSourcePattern != null
channelBundleId,
transportNamespace,
channelIQ.isInitiator(),
channelIQ.getRTPLevelRelayType());
channelIQ.getRTPLevelRelayType(),
channelIQ.getReceivingSimulcastLayer());
channelCreated = true;
}
}
Expand Down
1 change: 1 addition & 0 deletions src/main/java/org/jitsi/videobridge/health/Health.java
Expand Up @@ -96,6 +96,7 @@ private static void check(Conference conference)
channelBundleId,
/* transportNamespace */ null,
initiator,
null,
null);

// Fail as quickly as possible.
Expand Down
15 changes: 4 additions & 11 deletions src/main/java/org/jitsi/videobridge/simulcast/SimulcastSender.java
Expand Up @@ -86,17 +86,8 @@ public int getTargetOrder()

/**
* The simulcast target order for this <tt>SimulcastSender</tt>.
*
* XXX Defaulting to the lowest-quality simulcast stream until we are
* explicitly told to switch to a higher-quality simulcast stream is one way
* to go, of course. But such a default presents the problem that a remote
* peer will see the lowest quality possible for a noticeably long period of
* time because its command to switch to the highest quality possible can
* only come via its data/SCTP channel and that may take a very (and
* unpredictably) long time to set up. That is why we may default to the
* highest-quality simulcast stream here.
*/
private int targetOrder = SimulcastStream.SIMULCAST_LAYER_ORDER_BASE; // Integer.MAX_VALUE;
private int targetOrder;

/**
* Indicates whether this <tt>SimulcastSender</tt> has been initialized or
Expand All @@ -113,13 +104,15 @@ public int getTargetOrder()
*/
public SimulcastSender(
SimulcastSenderManager simulcastSenderManager,
SimulcastReceiver simulcastReceiver)
SimulcastReceiver simulcastReceiver,
int targetOrder)
{
this.simulcastSenderManager = simulcastSenderManager;

// We don't own the receiver, keep a weak reference so that it can be
// garbage collected.
this.weakSimulcastReceiver = new WeakReference<>(simulcastReceiver);
this.targetOrder = targetOrder;
}

/**
Expand Down
Expand Up @@ -137,7 +137,15 @@ private synchronized SimulcastSender getOrCreateSimulcastSender(

if (simulcastSender == null) // Create a new sender.
{
simulcastSender = new SimulcastSender(this, simulcastReceiver);
// Create a new sender.
int targetOrder = simulcastEngine.
getVideoChannel().
getReceiveSimulcastLayer();

simulcastSender = new SimulcastSender(
this,
simulcastReceiver,
targetOrder);

// TODO remove stuff from the map (not strictly necessary as they'll
// get garbage collected).
Expand Down