aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSebastien Vincent <seb@jitsi.org>2011-09-09 14:18:23 +0000
committerSebastien Vincent <seb@jitsi.org>2011-09-09 14:18:23 +0000
commit0689be4465c98ddd66ba4cd5f1d896e92bb450ca (patch)
tree2fd116b86fb0cc762e1fe190376f4c6dbb03655b /src
parent6bfac2a25708f2b887cba64eaec8adc2d13f2084 (diff)
downloadjitsi-0689be4465c98ddd66ba4cd5f1d896e92bb450ca.zip
jitsi-0689be4465c98ddd66ba4cd5f1d896e92bb450ca.tar.gz
jitsi-0689be4465c98ddd66ba4cd5f1d896e92bb450ca.tar.bz2
Fixes an RTP timestamp problem in iLBC packetization which breaks audio input on Android devices. Also fixes iLBC depacketization when there are several iLBC frames in RTP packet (typically N900 mobile device will send such packets with two iLBC frames).
Diffstat (limited to 'src')
-rw-r--r--src/net/java/sip/communicator/impl/neomedia/codec/audio/ilbc/JavaDecoder.java58
-rw-r--r--src/net/java/sip/communicator/impl/neomedia/codec/audio/ilbc/JavaEncoder.java52
2 files changed, 102 insertions, 8 deletions
diff --git a/src/net/java/sip/communicator/impl/neomedia/codec/audio/ilbc/JavaDecoder.java b/src/net/java/sip/communicator/impl/neomedia/codec/audio/ilbc/JavaDecoder.java
index 048d154..b7f2e97 100644
--- a/src/net/java/sip/communicator/impl/neomedia/codec/audio/ilbc/JavaDecoder.java
+++ b/src/net/java/sip/communicator/impl/neomedia/codec/audio/ilbc/JavaDecoder.java
@@ -6,6 +6,8 @@
*/
package net.java.sip.communicator.impl.neomedia.codec.audio.ilbc;
+import java.util.*;
+
import javax.media.*;
import javax.media.format.*;
@@ -27,11 +29,16 @@ public class JavaDecoder
private ilbc_decoder dec;
/**
- * The input length in bytes with which {@link #dec} has been initialized.
+ * The input length in bytes with which {@link #dec} has been initialized.
*/
private int inputLength;
/**
+ * List of offsets for a "more than one" iLBC frame per RTP packet.
+ */
+ private List<Integer> offsets = new ArrayList<Integer>();
+
+ /**
* Initializes a new iLBC <tt>JavaDecoder</tt> instance.
*/
public JavaDecoder()
@@ -91,25 +98,64 @@ public class JavaDecoder
protected int doProcess(Buffer inputBuffer, Buffer outputBuffer)
{
byte[] input = (byte[]) inputBuffer.getData();
-
int inputLength = inputBuffer.getLength();
- if (this.inputLength != inputLength)
- initDec(inputLength);
+ if(offsets.size() == 0 &&
+ ((inputLength > ilbc_constants.NO_OF_BYTES_20MS &&
+ inputLength != ilbc_constants.NO_OF_BYTES_30MS) ||
+ inputLength > ilbc_constants.NO_OF_BYTES_30MS))
+ {
+ int nb = 0;
+ int len = 0;
+
+ if((inputLength % ilbc_constants.NO_OF_BYTES_20MS) == 0)
+ {
+ nb = (inputLength % ilbc_constants.NO_OF_BYTES_20MS);
+ len = ilbc_constants.NO_OF_BYTES_20MS;
+ }
+ else if((inputLength % ilbc_constants.NO_OF_BYTES_30MS) == 0)
+ {
+ nb = (inputLength % ilbc_constants.NO_OF_BYTES_30MS);
+ len = ilbc_constants.NO_OF_BYTES_30MS;
+ }
+
+ if (this.inputLength != len)
+ initDec(len);
+
+ for(int i = 0 ; i < nb ; i++)
+ {
+ offsets.add(new Integer(inputLength + (i * len)));
+ }
+ }
+ else
+ if (this.inputLength != inputLength)
+ initDec(inputLength);
int outputLength = dec.ULP_inst.blockl * 2;
byte[] output = validateByteArraySize(outputBuffer, outputLength);
int outputOffset = 0;
+ int offsetToAdd = 0;
+
+ if(offsets.size() > 0)
+ offsetToAdd = offsets.remove(0).intValue();
+
dec.decode(
output, outputOffset,
- input, inputBuffer.getOffset(),
+ input, inputBuffer.getOffset() + offsetToAdd,
(short) 1);
updateOutput(
outputBuffer,
getOutputFormat(), outputLength, outputOffset);
- return BUFFER_PROCESSED_OK;
+ int flags = BUFFER_PROCESSED_OK;
+
+ if(offsets.size() > 0)
+ {
+ flags |= INPUT_BUFFER_NOT_CONSUMED;
+ }
+
+ return flags;
}
@Override
diff --git a/src/net/java/sip/communicator/impl/neomedia/codec/audio/ilbc/JavaEncoder.java b/src/net/java/sip/communicator/impl/neomedia/codec/audio/ilbc/JavaEncoder.java
index 35a55fd..dc2371d 100644
--- a/src/net/java/sip/communicator/impl/neomedia/codec/audio/ilbc/JavaEncoder.java
+++ b/src/net/java/sip/communicator/impl/neomedia/codec/audio/ilbc/JavaEncoder.java
@@ -20,7 +20,6 @@ import net.java.sip.communicator.impl.neomedia.codec.*;
public class JavaEncoder
extends AbstractCodecExt
{
-
/**
* The <tt>ilbc_encoder</tt> adapted to <tt>Codec</tt> by this instance.
*/
@@ -49,6 +48,11 @@ public class JavaEncoder
private int prevInputLength;
/**
+ * The duration an output <tt>Buffer</tt> produced by this <tt>Codec</tt>.
+ */
+ private int duration = 0;
+
+ /**
* Initializes a new iLBC <tt>JavaEncoder</tt> instance.
*/
public JavaEncoder()
@@ -98,6 +102,7 @@ public class JavaEncoder
inputLength = 0;
prevInput = null;
prevInputLength = 0;
+ duration = 0;
}
/**
@@ -122,12 +127,54 @@ public class JavaEncoder
default:
throw new IllegalStateException("mode");
}
+ /* mode is 20 or 30 ms, duration must be in nanoseconds */
+ duration = mode * 1000000;
inputLength = enc.ULP_inst.blockl * 2;
prevInput = new byte[inputLength];
prevInputLength = 0;
}
/**
+ * Get the output format.
+ *
+ * @return output format
+ * @see net.sf.fmj.media.AbstractCodec#getOutputFormat()
+ */
+ @Override
+ public Format getOutputFormat()
+ {
+ Format outputFormat = super.getOutputFormat();
+
+ if ((outputFormat != null)
+ && (outputFormat.getClass() == AudioFormat.class))
+ {
+ AudioFormat outputAudioFormat = (AudioFormat) outputFormat;
+
+ outputFormat = setOutputFormat(
+ new AudioFormat(
+ outputAudioFormat.getEncoding(),
+ outputAudioFormat.getSampleRate(),
+ outputAudioFormat.getSampleSizeInBits(),
+ outputAudioFormat.getChannels(),
+ outputAudioFormat.getEndian(),
+ outputAudioFormat.getSigned(),
+ outputAudioFormat.getFrameSizeInBits(),
+ outputAudioFormat.getFrameRate(),
+ outputAudioFormat.getDataType())
+ {
+ private static final long serialVersionUID = 0L;
+
+ @Override
+ public long computeDuration(long length)
+ {
+ return JavaEncoder.this.duration;
+ }
+ });
+ }
+ return outputFormat;
+ }
+
+ /**
* Implements {@link AbstractCodecExt#doProcess(Buffer, Buffer)}.
*
* @param inputBuffer
@@ -188,7 +235,8 @@ public class JavaEncoder
updateOutput(
outputBuffer,
- outputFormat, outputLength, outputOffset);
+ getOutputFormat(), outputLength, outputOffset);
+ outputBuffer.setDuration(duration);
ret = BUFFER_PROCESSED_OK;
}
else