diff --git a/lib/native/linux-64/libjnopus.so b/lib/native/linux-64/libjnopus.so
index 5a73eaafb66e390c09a03b0e63c399b05e293982..045fa4c9380c3edd33a2f64ea52f38de125bca99 100755
Binary files a/lib/native/linux-64/libjnopus.so and b/lib/native/linux-64/libjnopus.so differ
diff --git a/lib/native/linux/libjnopus.so b/lib/native/linux/libjnopus.so
index c55810f143401615df5c95484546ef779b469fd7..6fa870980561270879197d815d78ca7928b8b7d9 100755
Binary files a/lib/native/linux/libjnopus.so and b/lib/native/linux/libjnopus.so differ
diff --git a/lib/native/mac/libjnopus.jnilib b/lib/native/mac/libjnopus.jnilib
index 7b58804f5b41e2c9dfb88a3ce0fa9d1be6a6ab7c..72550c2d067d739a2f1019366379b6bcff8d9049 100755
Binary files a/lib/native/mac/libjnopus.jnilib and b/lib/native/mac/libjnopus.jnilib differ
diff --git a/lib/native/windows-64/jnopus.dll b/lib/native/windows-64/jnopus.dll
index 02ddb34c378d3712b74771d49786b056e48e8bc5..903c582080ae1bb972f2cbe427514944f2cdf8e0 100755
Binary files a/lib/native/windows-64/jnopus.dll and b/lib/native/windows-64/jnopus.dll differ
diff --git a/lib/native/windows/jnopus.dll b/lib/native/windows/jnopus.dll
index 961fb5be44ddfe082a3dd9b8558ce7c69c2f8864..4e4e6d8f5816d5c622ab0d9e5adff39f6ce275b9 100755
Binary files a/lib/native/windows/jnopus.dll and b/lib/native/windows/jnopus.dll differ
diff --git a/src/native/opus/org_jitsi_impl_neomedia_codec_audio_opus_Opus.c b/src/native/opus/org_jitsi_impl_neomedia_codec_audio_opus_Opus.c
index 55058e782d74c31806bf0f2ca957fc155af6037b..0a07a0f000ef3e89ca548c44fbf896a06f335af9 100644
--- a/src/native/opus/org_jitsi_impl_neomedia_codec_audio_opus_Opus.c
+++ b/src/native/opus/org_jitsi_impl_neomedia_codec_audio_opus_Opus.c
@@ -66,12 +66,30 @@ JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_encode
     return (jint) opus_encoder_ctl((OpusEncoder *)(intptr_t)encoder, OPUS_SET_VBR(use_vbr));
 }
 
+JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_encoder_1get_1vbr
+  (JNIEnv *env, jclass clazz, jlong encoder)
+{
+    int x, ret;
+    ret = opus_encoder_ctl((OpusEncoder *)(intptr_t)encoder, OPUS_GET_VBR(&x));
+    if(ret<0) return ret;
+    return x;
+}
+
 JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_encoder_1set_1vbr_1constraint
   (JNIEnv *env, jclass clazz, jlong encoder, jint use_cvbr)
 {
     return (jint) opus_encoder_ctl((OpusEncoder *)(intptr_t)encoder, OPUS_SET_VBR_CONSTRAINT(use_cvbr));
 }
 
+JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_encoder_1get_1vbr_1constraint
+  (JNIEnv *env, jclass clazz, jlong encoder)
+{
+    int x, ret;
+    ret = opus_encoder_ctl((OpusEncoder *)(intptr_t)encoder, OPUS_GET_VBR_CONSTRAINT(&x));
+    if(ret<0) return ret;
+    return x;
+}
+
 JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_encoder_1set_1complexity
   (JNIEnv *env, jclass clazz, jlong encoder, jint complexity)
 {
@@ -96,6 +114,27 @@ JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_encode
     return (jint) opus_encoder_ctl((OpusEncoder *)(intptr_t)encoder, OPUS_SET_DTX(use_dtx));
 }
 
+JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_encoder_1get_1dtx
+  (JNIEnv *env, jclass clazz, jlong encoder)
+{
+    int x, ret;
+    ret = opus_encoder_ctl((OpusEncoder *)(intptr_t)encoder, OPUS_GET_DTX(&x));
+    if(ret<0) return ret;
+    return x;
+}
+
+JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_encoder_1set_1packet_1loss_1perc
+  (JNIEnv *env, jclass clazz, jlong encoder, jint percentage)
+{
+    return (jint) opus_encoder_ctl((OpusEncoder *)(intptr_t)encoder, OPUS_SET_PACKET_LOSS_PERC(percentage));
+}
+
+JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_encoder_1set_1max_1bandwidth
+  (JNIEnv *env, jclass clazz, jlong encoder, jint max_bandwidth)
+{
+    return (jint) opus_encoder_ctl((OpusEncoder *)(intptr_t)encoder, OPUS_SET_MAX_BANDWIDTH(max_bandwidth));
+}
+
 JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_encode
   (JNIEnv *env, jclass clazz, jlong encoder, jbyteArray input, jint inputOffset, jint frameSize, jbyteArray output, jint outputSize)
 {
@@ -148,7 +187,7 @@ JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_decode
 }
 
 JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_decode
-  (JNIEnv *env, jclass clazz, jlong decoder, jbyteArray input, jint inputOffset, jint inputSize, jbyteArray output, jint outputSize)
+  (JNIEnv *env, jclass clazz, jlong decoder, jbyteArray input, jint inputOffset, jint inputSize, jbyteArray output, jint outputSize, jint decodeFEC)
 {
     jbyte *inputPtr = (*env)->GetByteArrayElements(env, input, NULL);
     jbyte *outputPtr = (*env)->GetByteArrayElements(env, output, NULL);
@@ -158,10 +197,10 @@ JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_decode
     {
         ret = opus_decode((OpusDecoder *)(intptr_t)decoder,
                 (unsigned char *) ((char *)inputPtr + inputOffset),
-		(int) inputSize,
+        (int) inputSize,
                 (opus_int16 *)outputPtr,
-		(int) outputSize,
-		0);
+        (int) outputSize,
+        (int) decodeFEC);
     }
     else
         ret = 0;
@@ -181,7 +220,7 @@ JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_packet
     jint bandwidth = 0;
     if(packetPtr){
         bandwidth = (jint) opus_packet_get_bandwidth((unsigned char *)packetPtr+offset);
-	(*env)->ReleaseByteArrayElements(env, packet, packetPtr, JNI_ABORT);
+    (*env)->ReleaseByteArrayElements(env, packet, packetPtr, JNI_ABORT);
     }
     return bandwidth;
 }
@@ -193,7 +232,7 @@ JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_packet
     jint channels = 0;
     if(packetPtr){
         channels = (jint) opus_packet_get_nb_channels((unsigned char *)packetPtr+offset);
-	(*env)->ReleaseByteArrayElements(env, packet, packetPtr, JNI_ABORT);
+    (*env)->ReleaseByteArrayElements(env, packet, packetPtr, JNI_ABORT);
     }
     return channels;
 }
@@ -205,7 +244,7 @@ JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_packet
     jint frames = 0;
     if(packetPtr){
         frames = (jint) opus_packet_get_nb_frames((unsigned char *)packetPtr+offset, len);
-	(*env)->ReleaseByteArrayElements(env, packet, packetPtr, JNI_ABORT);
+    (*env)->ReleaseByteArrayElements(env, packet, packetPtr, JNI_ABORT);
     }
     return frames;
 }
@@ -220,6 +259,6 @@ JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_decode
         samples = opus_decoder_get_nb_samples((OpusDecoder*)(intptr_t)decoder, (unsigned char *)packetPtr+offset, len);
     }
     if(packetPtr)
-	(*env)->ReleaseByteArrayElements(env, packet, packetPtr, JNI_ABORT);
+    (*env)->ReleaseByteArrayElements(env, packet, packetPtr, JNI_ABORT);
     return samples;
 }
diff --git a/src/native/opus/org_jitsi_impl_neomedia_codec_audio_opus_Opus.h b/src/native/opus/org_jitsi_impl_neomedia_codec_audio_opus_Opus.h
index 57f053967070e5e897a74d5d86111cfa5725b592..d9b71c8a772a983e6ac19645cd161521613e6f17 100644
--- a/src/native/opus/org_jitsi_impl_neomedia_codec_audio_opus_Opus.h
+++ b/src/native/opus/org_jitsi_impl_neomedia_codec_audio_opus_Opus.h
@@ -19,6 +19,8 @@ extern "C" {
 #define org_jitsi_impl_neomedia_codec_audio_opus_Opus_BANDWIDTH_FULLBAND 1105L
 #undef org_jitsi_impl_neomedia_codec_audio_opus_Opus_OPUS_OK
 #define org_jitsi_impl_neomedia_codec_audio_opus_Opus_OPUS_OK 0L
+#undef org_jitsi_impl_neomedia_codec_audio_opus_Opus_OPUS_AUTO
+#define org_jitsi_impl_neomedia_codec_audio_opus_Opus_OPUS_AUTO -1000L
 #undef org_jitsi_impl_neomedia_codec_audio_opus_Opus_INVALID_PACKET
 #define org_jitsi_impl_neomedia_codec_audio_opus_Opus_INVALID_PACKET -4L
 #undef org_jitsi_impl_neomedia_codec_audio_opus_Opus_MAX_PACKET
@@ -87,6 +89,14 @@ JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_encode
 JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_encoder_1set_1vbr
   (JNIEnv *, jclass, jlong, jint);
 
+/*
+ * Class:     org_jitsi_impl_neomedia_codec_audio_opus_Opus
+ * Method:    encoder_get_vbr
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_encoder_1get_1vbr
+  (JNIEnv *, jclass, jlong);
+
 /*
  * Class:     org_jitsi_impl_neomedia_codec_audio_opus_Opus
  * Method:    encoder_set_vbr_constraint
@@ -95,6 +105,14 @@ JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_encode
 JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_encoder_1set_1vbr_1constraint
   (JNIEnv *, jclass, jlong, jint);
 
+/*
+ * Class:     org_jitsi_impl_neomedia_codec_audio_opus_Opus
+ * Method:    encoder_get_vbr_constraint
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_encoder_1get_1vbr_1constraint
+  (JNIEnv *, jclass, jlong);
+
 /*
  * Class:     org_jitsi_impl_neomedia_codec_audio_opus_Opus
  * Method:    encoder_set_complexity
@@ -127,6 +145,30 @@ JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_encode
 JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_encoder_1set_1dtx
   (JNIEnv *, jclass, jlong, jint);
 
+/*
+ * Class:     org_jitsi_impl_neomedia_codec_audio_opus_Opus
+ * Method:    encoder_get_dtx
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_encoder_1get_1dtx
+  (JNIEnv *, jclass, jlong);
+
+/*
+ * Class:     org_jitsi_impl_neomedia_codec_audio_opus_Opus
+ * Method:    encoder_set_packet_loss_perc
+ * Signature: (JI)I
+ */
+JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_encoder_1set_1packet_1loss_1perc
+  (JNIEnv *, jclass, jlong, jint);
+
+/*
+ * Class:     org_jitsi_impl_neomedia_codec_audio_opus_Opus
+ * Method:    encoder_set_max_bandwidth
+ * Signature: (JI)I
+ */
+JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_encoder_1set_1max_1bandwidth
+  (JNIEnv *, jclass, jlong, jint);
+
 /*
  * Class:     org_jitsi_impl_neomedia_codec_audio_opus_Opus
  * Method:    encode
@@ -162,10 +204,10 @@ JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_decode
 /*
  * Class:     org_jitsi_impl_neomedia_codec_audio_opus_Opus
  * Method:    decode
- * Signature: (J[BII[BI)I
+ * Signature: (J[BII[BII)I
  */
 JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_decode
-  (JNIEnv *, jclass, jlong, jbyteArray, jint, jint, jbyteArray, jint);
+  (JNIEnv *, jclass, jlong, jbyteArray, jint, jint, jbyteArray, jint, jint);
 
 /*
  * Class:     org_jitsi_impl_neomedia_codec_audio_opus_Opus
diff --git a/src/org/jitsi/impl/neomedia/MediaStreamImpl.java b/src/org/jitsi/impl/neomedia/MediaStreamImpl.java
index 662adf1f98f2cad71a3dc9048b996aa14d0f3a47..a521d1126c4a3be848b6c808af94b1d6be6afcd6 100644
--- a/src/org/jitsi/impl/neomedia/MediaStreamImpl.java
+++ b/src/org/jitsi/impl/neomedia/MediaStreamImpl.java
@@ -202,6 +202,11 @@ else if (MediaDeviceSession.SSRC_LIST.equals(propertyName))
      */
     private long numberOfReceivedSenderReports = 0;
 
+    /**
+     * Number of received receiver reports. Used for logging and debugging only.
+     */
+    private long numberOfReceivedReceiverReports = 0;
+
     /**
      * The minimum inter arrival jitter value the other party has reported.
      */
@@ -229,6 +234,12 @@ else if (MediaDeviceSession.SSRC_LIST.equals(propertyName))
      */
     private PayloadTypeTransformEngine ptTransformEngine;
 
+    /**
+     * The <tt>PacketLossAwareEncoder</tt> in the encoding codec chain, which
+     * is to be notified of packet loss information received via RTCP.
+     */
+    PacketLossAwareEncoder packetLossAwareEncoder = null;
+
     /**
      * Initializes a new <tt>MediaStreamImpl</tt> instance which will use the
      * specified <tt>MediaDevice</tt> for both capture and playback of media.
@@ -2495,15 +2506,22 @@ public void update(SessionEvent event)
      */
     public void update(RemoteEvent remoteEvent)
     {
-        if(!logger.isInfoEnabled())
-            return;
-
-        if(remoteEvent instanceof SenderReportEvent)
+        if(remoteEvent instanceof SenderReportEvent ||
+                remoteEvent instanceof ReceiverReportEvent)
         {
-            numberOfReceivedSenderReports++;
-
-            SenderReport report =
-                    ((SenderReportEvent)remoteEvent).getReport();
+            Report report;
+            boolean senderReport = false;
+            if(remoteEvent instanceof SenderReportEvent)
+            {
+                numberOfReceivedSenderReports++;
+                report = ((SenderReportEvent)remoteEvent).getReport();
+                senderReport = true;
+            }
+            else
+            {
+                numberOfReceivedReceiverReports++;
+                report = ((ReceiverReportEvent)remoteEvent).getReport();
+            }
 
             Feedback feedback = null;
             long remoteJitter = -1;
@@ -2522,36 +2540,55 @@ public void update(RemoteEvent remoteEvent)
                     maxRemoteInterArrivalJitter = remoteJitter;
             }
 
-            // As sender reports are received on every 5 seconds
-            // print every 4th packet, on every 20 seconds
-            if(numberOfReceivedSenderReports%4 != 1)
-                return;
+            //Notify the encoder of the percentage of packets lost by the
+            //other side. See RFC3550 Section 6.4.1 for the interpretation of
+            //'fraction lost'
+            PacketLossAwareEncoder plae = getPacketLossAwareEncoder();
+            if(plae != null)
+                plae.setExpectedPacketLoss(
+                        (int) ((feedback.getFractionLost() * 100) / 256));
 
-            StringBuilder buff
-                = new StringBuilder(StatisticsEngine.RTP_STAT_PREFIX);
-            MediaType mediaType = getMediaType();
-            String mediaTypeStr
-                = (mediaType == null) ? "" : mediaType.toString();
-
-            buff.append("Received a report for ")
-                .append(mediaTypeStr)
-                .append(" stream SSRC:")
-                .append(getLocalSourceID())
-                .append(" [packet count:")
-                .append(report.getSenderPacketCount())
-                .append(", bytes:").append(report.getSenderByteCount());
+            if(logger.isInfoEnabled())
+            {
+                // As reports are received on every 5 seconds
+                // print every 4th packet, on every 20 seconds
+                if((numberOfReceivedSenderReports
+                        + numberOfReceivedReceiverReports)%4 != 1)
+                    return;
+
+                StringBuilder buff
+                    = new StringBuilder(StatisticsEngine.RTP_STAT_PREFIX);
+                MediaType mediaType = getMediaType();
+                String mediaTypeStr
+                    = (mediaType == null) ? "" : mediaType.toString();
+
+                buff.append("Received a ")
+                    .append(senderReport ? "sender" : "receiver")
+                    .append(" report for ")
+                    .append(mediaTypeStr)
+                    .append(" stream SSRC:")
+                    .append(getLocalSourceID())
+                    .append(" [");
+                if(senderReport)
+                {
+                    buff.append("packet count:")
+                        .append(((SenderReport) report).getSenderPacketCount())
+                        .append(", bytes:")
+                        .append(((SenderReport) report).getSenderByteCount());
+                }
 
                 if(feedback != null)
                 {
                     buff.append(", interarrival jitter:")
-                            .append(remoteJitter)
-                    .append(", lost packets:").append(feedback.getNumLost())
-                    .append(", time since previous report:")
-                            .append((int) (feedback.getDLSR() / 65.536))
-                            .append("ms");
+                        .append(remoteJitter)
+                        .append(", lost packets:").append(feedback.getNumLost())
+                        .append(", time since previous report:")
+                        .append((int) (feedback.getDLSR() / 65.536))
+                        .append("ms");
                 }
-            buff.append(" ]");
-            logger.info(buff);
+                buff.append(" ]");
+                logger.info(buff);
+            }
         }
     }
 
@@ -2860,7 +2897,7 @@ public FECDecoderControl getFecDecoderControl(ReceiveStream receiveStream)
 
     /**
      * Adds an additional RTP payload mapping that will overriding one that
-     * we've set with {@link addDynamicRTPPayloadType(byte, MediaFormat)}.
+     * we've set with {@link #addDynamicRTPPayloadType(byte, MediaFormat)}.
      * This is necessary so that we can support the RFC3264 case where the
      * answerer has the right to declare what payload type mappings it wants to
      * receive RTP packets with even if they are different from those in the
@@ -2880,4 +2917,37 @@ public void addDynamicRTPPayloadTypeOverride(byte originalPt,
             ptTransformEngine.addPTMappingOverride(originalPt, overloadPt);
         }
     }
+
+    /**
+     * Gets this <tt>MediaDevice</tt>'s <tt>PacketLossAwareEncoder</tt> if any,
+     * <tt>null</tt> otherwise. To find such an instance, the codec chain
+     * contained in the <tt>DeviceSession</tt>'s processor is searched.
+     *
+     * @return this <tt>MediaDevice</tt>'s <tt>PacketLossAwareEncoder</tt> if
+     * any, <tt>null</tt> otherwise.
+     */
+    public PacketLossAwareEncoder getPacketLossAwareEncoder()
+    {
+        if(packetLossAwareEncoder != null)
+            return packetLossAwareEncoder;
+
+        MediaDeviceSession mediaDeviceSession = getDeviceSession();
+        if(mediaDeviceSession == null)
+            return null;
+        Processor processor = mediaDeviceSession.getProcessor();
+        if(processor == null)
+            return null;
+
+        for(TrackControl tc : processor.getTrackControls())
+        {
+            Object obj
+                    = tc.getControl(PacketLossAwareEncoder.class.getName());
+            if(obj instanceof PacketLossAwareEncoder)
+            {
+                packetLossAwareEncoder = (PacketLossAwareEncoder)obj;
+                return packetLossAwareEncoder;
+            }
+        }
+        return packetLossAwareEncoder;
+    }
 }
diff --git a/src/org/jitsi/impl/neomedia/MediaUtils.java b/src/org/jitsi/impl/neomedia/MediaUtils.java
index 3b539b9b5135844d78a9ead7fa9e6e7a6a93cc8d..fa5038da2fb5a8b8ddb12d3e5092d1a334b87afe 100644
--- a/src/org/jitsi/impl/neomedia/MediaUtils.java
+++ b/src/org/jitsi/impl/neomedia/MediaUtils.java
@@ -169,8 +169,7 @@ public class MediaUtils
         ConfigurationService cfg = LibJitsi.getConfigurationService();
 
         boolean advertiseFEC
-                = cfg.getBoolean("net.java.sip.communicator.impl.neomedia" +
-                ".codec.audio.silk.ADVERTISE_FEC", false);
+                = cfg.getBoolean(Constants.PROP_SILK_ADVERSISE_FEC, false);
         Map<String,String> silkFormatParams = new HashMap<String, String>();
         if(advertiseFEC)
             silkFormatParams.put("useinbandfec", "1");
diff --git a/src/org/jitsi/impl/neomedia/codec/audio/opus/JNIDecoder.java b/src/org/jitsi/impl/neomedia/codec/audio/opus/JNIDecoder.java
index 1af80796104668b22a8da607f45774cba25b225a..40d1a50beea325be1d329180517457c4dbadef47 100644
--- a/src/org/jitsi/impl/neomedia/codec/audio/opus/JNIDecoder.java
+++ b/src/org/jitsi/impl/neomedia/codec/audio/opus/JNIDecoder.java
@@ -141,7 +141,7 @@ protected int doProcess(Buffer inputBuffer, Buffer outputBuffer)
         byte[] output = validateByteArraySize(outputBuffer, outputLength);
 
         int samplesCount = Opus.decode(decoder, input, inputOffset, inputLength,
-                                                output, outputLength);
+                                                output, outputLength, 0);
 
         if (samplesCount > 0)
         {
diff --git a/src/org/jitsi/impl/neomedia/codec/audio/opus/JNIEncoder.java b/src/org/jitsi/impl/neomedia/codec/audio/opus/JNIEncoder.java
index 9006edd44f4b40bd395e4c74f83b511c582875b1..013c9988dc204495d74ce53de5abaa0bea1844b0 100644
--- a/src/org/jitsi/impl/neomedia/codec/audio/opus/JNIEncoder.java
+++ b/src/org/jitsi/impl/neomedia/codec/audio/opus/JNIEncoder.java
@@ -10,7 +10,13 @@
 import javax.media.format.*;
 import net.sf.fmj.media.*;
 import org.jitsi.impl.neomedia.codec.*;
+import org.jitsi.service.configuration.*;
+import org.jitsi.service.libjitsi.*;
 import org.jitsi.service.neomedia.codec.*;
+import org.jitsi.service.neomedia.control.*;
+import org.jitsi.util.*;
+
+import java.awt.*;
 
 /**
  * Implements an opus encoder.
@@ -19,6 +25,7 @@
  */
 public class JNIEncoder
     extends AbstractCodecExt
+    implements PacketLossAwareEncoder
 {
     /**
      * The list of <tt>Format</tt>s of audio data supported as input by
@@ -44,6 +51,13 @@ public class JNIEncoder
     private static final Format[] SUPPORTED_OUTPUT_FORMATS
         = new Format[] { new AudioFormat(Constants.OPUS_RTP) };
 
+    /**
+     * The <tt>Logger</tt> used by this <tt>JNIEncoder</tt> instance
+     * for logging output.
+     */
+    private final Logger logger
+            = Logger.getLogger(JNIEncoder.class);
+
     /**
      * Set the supported input formats.
      */
@@ -111,6 +125,11 @@ public class JNIEncoder
      */
     private double frameSize = 20;
 
+    /**
+     * The minimum expected packet loss percentage to set to the encoder.
+     */
+    private int minPacketLoss = 0;
+
     /**
      * Returns the number of bytes that we need to read from the input buffer
      * in order ot fill a frame of <tt>frameSize</tt>. Depends on the input
@@ -123,14 +142,14 @@ public class JNIEncoder
     private int inputFrameSize()
     {
         int fs =
-	    (int) (
+        (int) (
            2 /* sizeof(short) */
            * channels
            *  ((AudioFormat)getInputFormat()).getSampleRate() /* samples in 1s */
            *   frameSize /* milliseconds */
            ) / 1000;
 
-	    return fs;
+        return fs;
     }
 
     /**
@@ -143,6 +162,8 @@ public JNIEncoder()
                SUPPORTED_OUTPUT_FORMATS);
 
         inputFormats = SUPPORTED_INPUT_FORMATS;
+
+        addControl(this);
     }
 
     /**
@@ -170,25 +191,61 @@ protected void doClose()
     protected void doOpen()
         throws ResourceUnavailableException
     {
-
-    //TODO: make a ParametrizedAudioFormat (or something) class, and use it here
-    //to set the encoder parameters
-	AudioFormat inputFormat = (AudioFormat) getInputFormat();
-	int sampleRate = (int)inputFormat.getSampleRate();
-    channels = inputFormat.getChannels();
-
-    encoder = Opus.encoder_create(sampleRate, channels);
-    if (encoder == 0)
-        throw new ResourceUnavailableException("opus_encoder_create()");
-
-    //set default encoder settings
-    Opus.encoder_set_bitrate(encoder, 60000);
-	Opus.encoder_set_bandwidth(encoder, Opus.BANDWIDTH_FULLBAND);
-	Opus.encoder_set_vbr(encoder, 1);
-	Opus.encoder_set_complexity(encoder, 10);
-	Opus.encoder_set_inband_fec(encoder, 0);
-	Opus.encoder_set_dtx(encoder, 1);
-	Opus.encoder_set_force_channels(encoder, 1);
+        AudioFormat inputFormat = (AudioFormat) getInputFormat();
+        int sampleRate = (int)inputFormat.getSampleRate();
+        channels = inputFormat.getChannels();
+
+        encoder = Opus.encoder_create(sampleRate, channels);
+        if (encoder == 0)
+            throw new ResourceUnavailableException("opus_encoder_create()");
+
+        //Set encoder options according to user configuration and SDP parameters
+        ConfigurationService cfg = LibJitsi.getConfigurationService();
+
+        //configuration is in kilobits per second
+        int bitrate = 1000 *
+                cfg.getInt(Constants.PROP_OPUS_BITRATE, 32);
+        //TODO:update bitrate from SDP (maxaveragebitrate)
+        //Note: If the parameter "maxaveragebitrate" is below the range specified
+        //in Section 3.1.1 the session MUST be rejected.
+        if(bitrate < 500 && bitrate != Opus.OPUS_AUTO)
+            bitrate = 500;
+        if(bitrate > 512000 && bitrate != Opus.OPUS_AUTO)
+            bitrate = 512000;
+
+        String bandwidthStr
+                = cfg.getString(Constants.PROP_OPUS_BANDWIDTH, "auto");
+        int bandwidth = Opus.OPUS_AUTO;
+        if("fb".equals(bandwidthStr))
+            bandwidth = Opus.BANDWIDTH_FULLBAND;
+        else if("swb".equals(bandwidthStr))
+            bandwidth = Opus.BANDWIDTH_SUPERWIDEBAND;
+        else if("wb".equals(bandwidthStr))
+            bandwidth = Opus.BANDWIDTH_WIDEBAND;
+        else if("mb".equals(bandwidthStr))
+            bandwidth = Opus.BANDWIDTH_MEDIUMBAND;
+        else if("nb".equals(bandwidthStr))
+            bandwidth = Opus.BANDWIDTH_NARROWBAND;
+
+        int complexity = cfg.getInt(Constants.PROP_OPUS_COMPLEXITY, 10);
+
+        boolean useFEC = cfg.getBoolean(Constants.PROP_OPUS_FEC, true);
+        //TODO:check SDP for useinbandfec
+
+        minPacketLoss = cfg.getInt(
+                Constants.PROP_OPUS_MIN_EXPECTED_PACKET_LOSS, 1);
+        boolean useDTX = cfg.getBoolean(Constants.PROP_OPUS_DTX, true);
+        //TODO:check SDP parameters for usedtx
+
+        //TODO:check SDP for maxcodedaudiobandwidth
+        //TODO: check {min,max,}ptime and adjust the frame size
+
+        Opus.encoder_set_bitrate(encoder, bitrate);
+        Opus.encoder_set_bandwidth(encoder, bandwidth);
+        Opus.encoder_set_complexity(encoder, complexity);
+        Opus.encoder_set_inband_fec(encoder, useFEC ? 1 : 0);
+        Opus.encoder_set_packet_loss_perc(encoder, minPacketLoss);
+        Opus.encoder_set_dtx(encoder, useDTX ? 1 : 0);
     }
 
     /**
@@ -211,14 +268,13 @@ protected int doProcess(Buffer inputBuffer, Buffer outputBuffer)
             if (null == setInputFormat(inputFormat))
                 return BUFFER_PROCESSED_FAILED;
         }
-        inputFormat = this.inputFormat;
 
         byte[] input = (byte[]) inputBuffer.getData();
         int inputLength = inputBuffer.getLength();
         int inputOffset = inputBuffer.getOffset();
 
 
-	    int inputBytesNeeded = inputFrameSize();
+        int inputBytesNeeded = inputFrameSize();
 
         if ((previousInput != null) && (previousInputLength > 0))
         {
@@ -299,7 +355,7 @@ else if (inputLength < inputBytesNeeded)
 
         byte[] output = validateByteArraySize(outputBuffer, Opus.MAX_PACKET);
 
-	    int outputLength = Opus.encode(encoder, input, inputOffset,
+        int outputLength = Opus.encode(encoder, input, inputOffset,
                 inputBytesNeeded / 2, output, Opus.MAX_PACKET);
 
 
@@ -412,4 +468,31 @@ public Format setInputFormat(Format format)
         }
         return inputFormat;
     }
+
+    /**
+     * Updates the encoder's expected packet loss percentage to the bigger of
+     * <tt>percentage</tt> and <tt>this.minPacketLoss</tt>.
+     *
+     * @param percentage the expected packet loss percentage to set
+     */
+    public void setExpectedPacketLoss(int percentage)
+    {
+        if(opened)
+            Opus.encoder_set_packet_loss_perc(encoder,
+                    (percentage > minPacketLoss) ? percentage : minPacketLoss);
+
+        if(logger.isTraceEnabled())
+            logger.trace("Updating expected packet loss: " + percentage
+                    + " (minimum " + minPacketLoss + ")");
+    }
+
+    /**
+     * Stub. Only added in order to implement the
+     * <tt>PacketLossAwareEncoder</tt> interface.
+     *
+     * @return null
+     */
+    public Component getControlComponent() {
+        return null;
+    }
 }
diff --git a/src/org/jitsi/impl/neomedia/codec/audio/opus/Opus.java b/src/org/jitsi/impl/neomedia/codec/audio/opus/Opus.java
index bf27ddaed3bf10ae4d3cdccdd39c52a02b2999ef..4115d208529126fd703a31dafe4f25772a53cdd5 100644
--- a/src/org/jitsi/impl/neomedia/codec/audio/opus/Opus.java
+++ b/src/org/jitsi/impl/neomedia/codec/audio/opus/Opus.java
@@ -8,6 +8,8 @@
 
 /**
  * Implements an interface to the native opus library
+ *
+ * @author Boris Grozev
  */
 public class Opus
 {
@@ -41,6 +43,11 @@ public class Opus
      */
     public static final int OPUS_OK = 0;
 
+    /**
+     * Constant used to set various settings to "automatic"
+     */
+    public static final int OPUS_AUTO = -1000;
+
     /**
      * Opus constant for an invalid packet
      */
@@ -139,6 +146,16 @@ public class Opus
      */
     public static native int encoder_set_vbr(long encoder, int use_vbr);
 
+    /**
+     * Wrapper around the native <tt>opus_encoder_ctl</tt> function. Returns the
+     * current encoder VBR setting
+     *
+     * @param encoder The encoder to use
+     *
+     * @return The current encoder VBR setting.
+     */
+    public static native int encoder_get_vbr(long encoder);
+
     /**
      * Wrapper around the native <tt>opus_encoder_ctl</tt> function. Sets the
      * encoder VBR constraint setting
@@ -151,6 +168,16 @@ public class Opus
     public static native int encoder_set_vbr_constraint(long encoder,
                                                         int use_cvbr);
 
+    /**
+     * Wrapper around the native <tt>opus_encoder_ctl</tt> function. Returns
+     * the current VBR constraint encoder setting.
+     *
+     * @param encoder The encoder to use
+     *
+     * @return the current VBR constraint encoder setting.
+     */
+    public static native int encoder_get_vbr_constraint(long encoder);
+
     /**
      * Wrapper around the native <tt>opus_encoder_ctl</tt> function. Sets the
      * encoder complexity setting.
@@ -197,6 +224,43 @@ public static native int encoder_set_force_channels(long encoder,
      */
     public static native int encoder_set_dtx(long encoder, int use_dtx);
 
+    /**
+     * Wrapper around the native <tt>opus_encoder_ctl</tt> function. Returns
+     * the current DTX setting of the encoder.
+     *
+     * @param encoder The encoder to use
+     *
+     * @return the current DTX setting of the encoder.
+     */
+    public static native int encoder_get_dtx(long encoder);
+
+    /**
+     * Wrapper around the native <tt>opus_encoder_ctl</tt> function. Sets the
+     * encoder's expected packet loss percentage.
+     *
+     * @param encoder The encoder to use
+     * @param percentage 0 to turn DTX off, non-zero to turn it on
+     *
+     * @return OPUS_OK on success.
+     */
+    public static native int encoder_set_packet_loss_perc(long encoder,
+                                                          int percentage);
+
+    /**
+     * Wrapper around the native <tt>opus_encoder_ctl</tt> function. Sets the
+     * maximum audio bandwidth to be used by the encoder.
+     *
+     * @param encoder The encoder to use
+     * @param maxBandwidth The maximum bandwidth to use, should be one of
+     *  <tt>BANDWIDTH_FULLBAND</tt>, <tt>BANDWIDTH_MEDIUMBAND</tt>,
+     *  <tt>BANDWIDTH_NARROWBAND</tt>, <tt>BANDWIDTH_SUPERWIDEBAND</tt> or
+     *  <tt>BANDWIDTH_WIDEBAND</tt>
+     *
+     * @return <tt>OPUS_OK</tt> on success.
+     */
+    public static native int encoder_set_max_bandwidth(long encoder,
+                                                       int maxBandwidth);
+
     /**
      * Encodes the input from <tt>input</tt> into an opus packet in
      * <tt>output</tt>.
@@ -254,12 +318,14 @@ public static native int encode(long encoder, byte[] input, int offset,
      * @param inputSize Size of the packet in bytes.
      * @param output Output buffer where the output will be stored.
      * @param outputSize Size in bytes of the output buffer.
+     * @param decodeFEC 0 to decode the packet normally, 1 to decode the FEC
+     * data in the packet.
      *
      * @return Number of samples decoded
      */
     public static native int decode(long decoder, byte[] input, int inputOffset,
                                     int inputSize, byte[] output,
-                                    int outputSize);
+                                    int outputSize, int decodeFEC);
 
     /**
      * Returns the audio bandwidth of an opus packet, one of
diff --git a/src/org/jitsi/impl/neomedia/codec/audio/silk/JavaEncoder.java b/src/org/jitsi/impl/neomedia/codec/audio/silk/JavaEncoder.java
index 3343af07588214585d232fc62c61551b921b159e..85073444e9e41b220ec3931c635b18b1cc9f11cf 100644
--- a/src/org/jitsi/impl/neomedia/codec/audio/silk/JavaEncoder.java
+++ b/src/org/jitsi/impl/neomedia/codec/audio/silk/JavaEncoder.java
@@ -13,15 +13,28 @@
 import org.jitsi.service.configuration.*;
 import org.jitsi.service.libjitsi.*;
 import org.jitsi.service.neomedia.codec.*;
+import org.jitsi.service.neomedia.control.*;
+import org.jitsi.util.*;
+
+import java.awt.*;
 
 /**
  * Implements the SILK encoder as an FMJ/JMF <tt>Codec</tt>.
  *
  * @author Dingxin Xu
+ * @author Boris Grozev
  */
 public class JavaEncoder
     extends AbstractCodecExt
+    implements PacketLossAwareEncoder
 {
+    /**
+     * The <tt>Logger</tt> used by this <tt>JavaEncoder</tt> instance
+     * for logging output.
+     */
+    private final Logger logger
+            = Logger.getLogger(JavaEncoder.class);
+
     private static final int BITRATE = 40000;
 
     private static final int COMPLEXITY = 2;
@@ -51,8 +64,34 @@ public class JavaEncoder
     private static final double[] SUPPORTED_SAMPLE_RATES
         = new double[] { 8000, 12000, 16000, 24000 };
 
+    /**
+     * Default value for the use DTX setting
+     */
     private static final boolean USE_DTX = false;
 
+    /**
+     * If <tt>alwaysExpectPacketLoss</tt> is <tt>true</tt> the expected
+     * packet loss will always be set at or above this threshold.
+     */
+    private static final int MIN_PACKET_LOSS_PERCENTAGE = 3;
+
+    /**
+     * Whether to use FEC or not.
+     */
+    private boolean useFec;
+
+    /**
+     * Whether to always assume packet loss and set the encoder's expected
+     * packet loss over <tt>MIN_PACKET_LOSS_PERCENTAGE</tt>.
+     */
+    private boolean alwaysAssumePacketLoss = true;
+
+    /**
+     * The actual expected packet loss. Defaults to 0 and can be updated by
+     * outside classes through <tt>PacketLossUpdater</tt> instances.
+     */
+    private int expectedPacketLoss = 0;
+
     /**
      * The duration an output <tt>Buffer</tt> produced by this <tt>Codec</tt>
      * in nanosecond.
@@ -118,6 +157,26 @@ public JavaEncoder()
         super("SILK Encoder", AudioFormat.class, SUPPORTED_OUTPUT_FORMATS);
 
         inputFormats = SUPPORTED_INPUT_FORMATS;
+
+        ConfigurationService cfg = LibJitsi.getConfigurationService();
+        //TODO: we should have a default value dependent on the SDP parameters
+        //here.
+        useFec = cfg.getBoolean(Constants.PROP_SILK_FEC, true);
+        alwaysAssumePacketLoss
+                = cfg.getBoolean(Constants.PROP_SILK_ASSUME_PL, true);
+
+        //Update the statically defined value for "speech activity threshold"
+        //according to our configuration
+        String satStr = cfg.getString(Constants.PROP_SILK_FEC_SAT, "0.5");
+        float sat = Silk_define_FLP.LBRR_SPEECH_ACTIVITY_THRES;
+        try
+        {
+            sat = Float.parseFloat(satStr);
+        }
+        catch (Exception e){}
+        Silk_define_FLP.LBRR_SPEECH_ACTIVITY_THRES = sat;
+
+        addControl(this);
     }
 
     protected void doClose()
@@ -141,37 +200,16 @@ protected void doOpen()
         int channels = inputFormat.getChannels();
 
 
-        ConfigurationService cfg = LibJitsi.getConfigurationService();
-        //TODO: we should have a default value dependent on the SDP parameters
-        //here.
-        boolean useFEC = cfg.getBoolean("net.java.sip.communicator.impl."
-                +"neomedia.codec.audio.silk.encoder.USE_FEC", true);
-        boolean assumePacketLoss = cfg.getBoolean("net.java.sip.communicator." +
-                "impl.neomedia.codec.audio.silk.encoder." +
-                "ALWAYS_ASSUME_PACKET_LOSS", true);
-
-        //Update the statically defined value for "speech activity threshold"
-        //according to our configuration
-        String satStr = cfg.getString("net.java.sip.communicator.impl.neomedia"
-                + ".codec.audio.silk.encoder.SPEECH_ACTIVITY_THRESHOLD", "0.5");
-        float sat = Silk_define_FLP.LBRR_SPEECH_ACTIVITY_THRES;
-        try
-        {
-            sat = Float.parseFloat(satStr);
-        }
-        catch (Exception e){}
-        Silk_define_FLP.LBRR_SPEECH_ACTIVITY_THRES = sat;
-
         encControl.API_sampleRate = (int) sampleRate;
         encControl.bitRate = BITRATE;
         encControl.complexity = COMPLEXITY;
         encControl.maxInternalSampleRate = encControl.API_sampleRate;
-        encControl.packetLossPercentage = assumePacketLoss ? 3 : 0;
+        setExpectedPacketLoss(0);
         encControl.packetSize
             = (int)
                 ((JavaDecoder.FRAME_DURATION * sampleRate * channels) / 1000);
         encControl.useDTX = USE_DTX ? 1 : 0;
-        encControl.useInBandFEC = useFEC ? 1 : 0;
+        encControl.useInBandFEC = useFec ? 1 : 0;
     }
 
     protected int doProcess(Buffer inputBuffer, Buffer outputBuffer)
@@ -324,4 +362,34 @@ public long computeDuration(long length)
         }
         return outputFormat;
     }
+
+    /**
+     * Updates the encoder's packet loss percentage. Takes into account
+     * <tt>this.alwaysAssumePacketLoss</tt>.
+     *
+     * @param percentage the expected packet loss percentage to set.
+     */
+    public void setExpectedPacketLoss(int percentage)
+    {
+        if(opened)
+        {
+            if(alwaysAssumePacketLoss &&
+                    MIN_PACKET_LOSS_PERCENTAGE >= percentage)
+                percentage = MIN_PACKET_LOSS_PERCENTAGE;
+            encControl.packetLossPercentage = percentage;
+            if(logger.isTraceEnabled())
+                logger.trace("Setting expected packet loss to: "
+                        + percentage);
+        }
+    }
+
+    /**
+     * Stub. Only added in order to implement the
+     * <tt>PacketLossAwareEncoder</tt> interface.
+     *
+     * @return null
+     */
+    public Component getControlComponent() {
+        return null;
+    }
 }
diff --git a/src/org/jitsi/impl/neomedia/device/MediaDeviceSession.java b/src/org/jitsi/impl/neomedia/device/MediaDeviceSession.java
index 3189bad1b0054208667c08c58630f45c23ce0d28..14c478cfcf7310110853b26cef0623cdc102f2e6 100644
--- a/src/org/jitsi/impl/neomedia/device/MediaDeviceSession.java
+++ b/src/org/jitsi/impl/neomedia/device/MediaDeviceSession.java
@@ -1026,7 +1026,7 @@ protected List<Player> getPlayers()
      * @return the JMF <tt>Processor</tt> which transcodes the
      * <tt>MediaDevice</tt> of this instance into the format of this instance
      */
-    private Processor getProcessor()
+    public Processor getProcessor()
     {
         if (processor == null)
             processor = createProcessor();
diff --git a/src/org/jitsi/service/neomedia/codec/Constants.java b/src/org/jitsi/service/neomedia/codec/Constants.java
index 7a842fe40444771424992e50118988cfcccaae26..a49ea44709a84d7ebb2b336abdcdd4d9e407fcbe 100644
--- a/src/org/jitsi/service/neomedia/codec/Constants.java
+++ b/src/org/jitsi/service/neomedia/codec/Constants.java
@@ -9,12 +9,13 @@
 import org.jitsi.util.*;
 
 /**
- * Allows start import of <tt>org.jitsi.impl.neomedia.codec</tt>
- * in order to get the constants define in
+ * Allows star import of <tt>org.jitsi.service.neomedia.codec</tt>
+ * in order to get the constants defined in
  * <tt>org.jitsi.service.neomedia.codec.Constants</tt> without star
  * import of <tt>org.jitsi.impl.neomedia.codec</tt>.
  *
  * @author Lubomir Marinov
+ * @author Boris Grozev
  */
 public class Constants
 {
@@ -110,6 +111,83 @@ public class Constants
      */
     public static final int VIDEO_HEIGHT;
 
+    /**
+     * The name of the property used to control whether FEC is enabled for SILK
+     */
+    public static final String PROP_SILK_FEC
+            = "net.java.sip.communicator.impl.neomedia.codec.audio.silk." +
+            "encoder.USE_FEC";
+
+    /**
+     * The name of the property used to control the the
+     * 'always assume packet loss' setting for SILK
+     */
+    public static final String PROP_SILK_ASSUME_PL
+            = "net.java.sip.communicator.impl.neomedia.codec.audio.silk." +
+            "encoder.AWLAYS_ASSUME_PACKET_LOSS";
+
+    /**
+     * The name of the property used to control the SILK
+     * 'speech activity threshold'
+     */
+    public static final String PROP_SILK_FEC_SAT
+            = "net.java.sip.communicator.impl.neomedia.codec.audio.silk." +
+            "encoder.SPEECH_ACTIVITY_THRESHOLD";
+
+    /**
+     * The name of the property used to control whether FEC support is
+     * advertised for SILK
+     */
+    public static final String PROP_SILK_ADVERSISE_FEC
+            = "net.java.sip.communicator.impl.neomedia.codec.audio.silk." +
+            "ADVERTISE_FEC";
+    /**
+     * The name of the property used to control the Opus encoder
+     * "audio bandwidth" setting
+     */
+    public static final String PROP_OPUS_BANDWIDTH
+            = "net.java.sip.communicator.impl.neomedia.codec.audio.opus." +
+            "encoder.AUDIO_BANDWIDTH";
+
+    /**
+     * The name of the property used to control the Opus encoder bitrate setting
+     */
+    public static final String PROP_OPUS_BITRATE
+            = "net.java.sip.communicator.impl.neomedia.codec.audio.opus." +
+            "encoder.BITRATE";
+
+    /**
+     * The name of the property used to control the Opus encoder "DTX" setting
+     */
+    public static final String PROP_OPUS_DTX
+            = "net.java.sip.communicator.impl.neomedia.codec.audio.opus." +
+            "encoder.DTX";
+
+    /**
+     * The name of the property used to control whether FEC is enabled for the
+     * Opus encoder
+     */
+    public static final String PROP_OPUS_FEC
+            = "net.java.sip.communicator.impl.neomedia.codec.audio.opus." +
+            "encoder.FEC";
+
+    /**
+     * The name of the property used to control the Opus encoder
+     * "minimum expected packet loss" setting
+     */
+    public static final String PROP_OPUS_MIN_EXPECTED_PACKET_LOSS
+            = "net.java.sip.communicator.impl.neomedia.codec.audio.opus." +
+            "encoder.MIN_EXPECTED_PACKET_LOSS";
+
+    /**
+     * The name of the property used to control the Opus encoder 'complexity'
+     * setting
+     */
+    public static final String PROP_OPUS_COMPLEXITY
+            = "net.java.sip.communicator.impl.neomedia.codec.audio.opus." +
+            "encoder.COMPLEXITY";
+
+
     static
     {
 
diff --git a/src/org/jitsi/service/neomedia/control/PacketLossAwareEncoder.java b/src/org/jitsi/service/neomedia/control/PacketLossAwareEncoder.java
new file mode 100644
index 0000000000000000000000000000000000000000..aa1c34ecc4e5792b933b7d25e79c71eb4ab4ae6d
--- /dev/null
+++ b/src/org/jitsi/service/neomedia/control/PacketLossAwareEncoder.java
@@ -0,0 +1,24 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package org.jitsi.service.neomedia.control;
+
+import javax.media.*;
+
+/**
+ * An interface used to notify encoders about the packet loss which is expected.
+ *
+ * @author Boris Grozev
+ */
+public interface PacketLossAwareEncoder extends Control
+{
+    /**
+     * Tells the encoder to expect <tt>percentage</tt> percent packet loss.
+     *
+     * @return the percentage of expected packet loss
+     */
+    public void setExpectedPacketLoss(int percentage);
+}