diff options
author | Lyubomir Marinov <lyubomir.marinov@jitsi.org> | 2010-12-15 09:21:42 +0000 |
---|---|---|
committer | Lyubomir Marinov <lyubomir.marinov@jitsi.org> | 2010-12-15 09:21:42 +0000 |
commit | 284e5dcac1bb26f78934547be887ece48c6aae0c (patch) | |
tree | fc071ddc49914d208fecf6f558cc25327e49634a /src/net | |
parent | 352c5f2509959e5c7ad8806aee67ecebbc60017f (diff) | |
download | jitsi-284e5dcac1bb26f78934547be887ece48c6aae0c.zip jitsi-284e5dcac1bb26f78934547be887ece48c6aae0c.tar.gz jitsi-284e5dcac1bb26f78934547be887ece48c6aae0c.tar.bz2 |
Fixes an incorrect removal of audio-level data by CSRC.
Diffstat (limited to 'src/net')
4 files changed, 104 insertions, 117 deletions
diff --git a/src/net/java/sip/communicator/impl/neomedia/audiolevel/AudioLevelEffect.java b/src/net/java/sip/communicator/impl/neomedia/audiolevel/AudioLevelEffect.java index 2d173c5..1d61e34 100644 --- a/src/net/java/sip/communicator/impl/neomedia/audiolevel/AudioLevelEffect.java +++ b/src/net/java/sip/communicator/impl/neomedia/audiolevel/AudioLevelEffect.java @@ -25,9 +25,19 @@ public class AudioLevelEffect implements Effect { /** - * The supported audio formats by this effect. + * The indicator which determines whether <tt>AudioLevelEffect</tt> + * instances are to perform the copying of the data from input + * <tt>Buffer</tt>s to output <tt>Buffer</tt>s themselves (e.g. using + * {@link System#arraycopy(Object, int, Object, int, int)}). */ - private Format[] supportedAudioFormats; + private static final boolean COPY_DATA_FROM_INPUT_TO_OUTPUT = true; + + /** + * The dispatcher of the events which handles the calculation and the event + * firing in different thread in order to now slow down the JMF codec chain. + */ + private final AudioLevelEventDispatcher eventDispatcher + = new AudioLevelEventDispatcher(); /** * Input Format @@ -40,11 +50,9 @@ public class AudioLevelEffect private AudioFormat outputFormat; /** - * The dispatcher of the events which handles the calculation and the event - * firing in different thread in order to now slow down the JMF codec chain. + * The supported audio formats by this effect. */ - private final AudioLevelEventDispatcher eventDispatcher - = new AudioLevelEventDispatcher(); + private Format[] supportedAudioFormats; /** * The minimum and maximum values of the scale @@ -67,7 +75,7 @@ public class AudioLevelEffect } /** - * Sets (or unsets if <tt>listener</tt> is <tt>null</tt>, the listener that + * Sets (or unsets if <tt>listener</tt> is <tt>null</tt>), the listener that * is going to be notified of audio level changes detected by this effect. * Given the semantics of the {@link AudioLevelEventDispatcher} this effect * would do no real work if no listener is set or if it is set to @@ -84,6 +92,7 @@ public class AudioLevelEffect /** * Lists all of the input formats that this codec accepts. + * * @return An array that contains the supported input <tt>Formats</tt>. */ public Format[] getSupportedInputFormats() @@ -93,8 +102,9 @@ public class AudioLevelEffect /** * Lists the output formats that this codec can generate. - * @param input The <tt>Format</tt> of the data to be used - * as input to the plug-in. + * + * @param input The <tt>Format</tt> of the data to be used as input to the + * plug-in. * @return An array that contains the supported output <tt>Formats</tt>. */ public Format[] getSupportedOutputFormats(Format input) @@ -115,6 +125,7 @@ public class AudioLevelEffect /** * Sets the format of the data to be input to this codec. + * * @param format The <tt>Format</tt> to be set. * @return The <tt>Format</tt> that was set. */ @@ -126,6 +137,7 @@ public class AudioLevelEffect /** * Sets the format for the data this codec outputs. + * * @param format The <tt>Format</tt> to be set. * @return The <tt>Format</tt> that was set. */ @@ -137,48 +149,59 @@ public class AudioLevelEffect /** * Performs the media processing defined by this codec. - * @param inputBuffer The <tt>Buffer</tt> that contains the media data - * to be processed. - * @param outputBuffer The <tt>Buffer</tt> in which to store - * the processed media data. + * + * @param inputBuffer The <tt>Buffer</tt> that contains the media data to be + * processed. + * @param outputBuffer The <tt>Buffer</tt> in which to store the processed + * media data. * @return <tt>BUFFER_PROCESSED_OK</tt> if the processing is successful. - * @see PlugIn + * @see PlugIn */ public int process(Buffer inputBuffer, Buffer outputBuffer) { - //copy the actual data from input to the output. - Object data = outputBuffer.getData(); - byte[] bufferData; - if (data instanceof byte[] && - ((byte[])data).length >= inputBuffer.getLength()) + if (COPY_DATA_FROM_INPUT_TO_OUTPUT) { - bufferData = (byte[])data; + // Copy the actual data from the input to the output. + Object data = outputBuffer.getData(); + int inputBufferLength = inputBuffer.getLength(); + byte[] bufferData; + + if ((data instanceof byte[]) && + (((byte[])data).length >= inputBufferLength)) + { + bufferData = (byte[])data; + } + else + { + bufferData = new byte[inputBufferLength]; + outputBuffer.setData(bufferData); + } + outputBuffer.setLength(inputBufferLength); + outputBuffer.setOffset(0); + + System.arraycopy( + inputBuffer.getData(), inputBuffer.getOffset(), + bufferData, 0, + inputBufferLength); + + // Now copy the remaining attributes. + outputBuffer.setFormat(inputBuffer.getFormat()); + outputBuffer.setHeader(inputBuffer.getHeader()); + outputBuffer.setSequenceNumber(inputBuffer.getSequenceNumber()); + outputBuffer.setTimeStamp(inputBuffer.getTimeStamp()); + outputBuffer.setFlags(inputBuffer.getFlags()); + outputBuffer.setDiscard(inputBuffer.isDiscard()); + outputBuffer.setEOM(inputBuffer.isEOM()); + outputBuffer.setDuration(inputBuffer.getDuration()); } else { - bufferData = new byte[inputBuffer.getLength()]; - outputBuffer.setData(bufferData); + outputBuffer.copy(inputBuffer); } - outputBuffer.setLength(inputBuffer.getLength()); - outputBuffer.setOffset(0); - - System.arraycopy( - inputBuffer.getData(), inputBuffer.getOffset(), bufferData, 0, - inputBuffer.getLength()); //now copy the output to the level dispatcher. eventDispatcher.addData(outputBuffer); - //now copy the rest of the data. - outputBuffer.setFormat(inputBuffer.getFormat()); - outputBuffer.setHeader(inputBuffer.getHeader()); - outputBuffer.setSequenceNumber(inputBuffer.getSequenceNumber()); - outputBuffer.setTimeStamp(inputBuffer.getTimeStamp()); - outputBuffer.setFlags(inputBuffer.getFlags()); - outputBuffer.setDiscard(inputBuffer.isDiscard()); - outputBuffer.setEOM(inputBuffer.isEOM()); - outputBuffer.setDuration(inputBuffer.getDuration()); - return BUFFER_PROCESSED_OK; } diff --git a/src/net/java/sip/communicator/impl/neomedia/audiolevel/AudioLevelMap.java b/src/net/java/sip/communicator/impl/neomedia/audiolevel/AudioLevelMap.java index 759cdb7..ef9533a 100644 --- a/src/net/java/sip/communicator/impl/neomedia/audiolevel/AudioLevelMap.java +++ b/src/net/java/sip/communicator/impl/neomedia/audiolevel/AudioLevelMap.java @@ -39,10 +39,9 @@ public class AudioLevelMap { //copy the levels matrix so that no one pulls it from under our feet. long[][] levelsRef = levels; - int csrcIndex = findCSRC(levelsRef, csrc); - if ( csrcIndex == -1) + if (csrcIndex == -1) { //we don't have the csrc in there yet so we need a new row. levels = appendCSRCToMatrix(levelsRef, csrc, level); @@ -54,7 +53,7 @@ public class AudioLevelMap } /** - * Removes <tt>csrc</tt> and it's mapped level from this map. + * Removes <tt>csrc</tt> and its mapped level from this map. * * @param csrc the CSRC ID that we'd like to remove from this map. * @@ -65,13 +64,12 @@ public class AudioLevelMap { //copy the levels matrix so that no one pulls it from under our feet. long[][] levelsRef = levels; - int index = findCSRC(levelsRef, csrc); - if ( index == -1) + if (index == -1) return false; - if( levelsRef.length == 1) + if (levelsRef.length == 1) { levels = null; return true; @@ -79,16 +77,12 @@ public class AudioLevelMap //copy levelsRef into newLevels ref making sure we skip the entry //containing the CSRC ID that we are trying to remove; - long[][] newLevelsRef = new long[levelsRef.length - 1][2]; - - for( int j=0, i = 0; i < levelsRef.length; i++ ) - { - if(levelsRef[i][0] == csrc) - continue; + long[][] newLevelsRef = new long[levelsRef.length - 1][]; - newLevelsRef[j][0] = levelsRef[i][0]; - newLevelsRef[j][1] = levelsRef[i][1]; - } + System.arraycopy(levelsRef, 0, newLevelsRef, 0, index); + System.arraycopy( + levelsRef, index + 1, + newLevelsRef, index, newLevelsRef.length - index); levels = newLevelsRef; return true; @@ -106,27 +100,9 @@ public class AudioLevelMap public int getLevel(long csrc) { long[][] levelsRef = levels; - int index = findCSRC(levelsRef, csrc); - if( index == -1) - return -1; - - return (int)levelsRef[index][1]; - } - - /** - * Returns a reference to the bi-directional array encapsulated by this map. - * Note that the actual array used by this map may change as soon as this - * method returns and its contents and order may hence no longer correspond - * to those in the returned array. - * - * @return a reference to the bi-directional array encapsulated by this map - * or <tt>null</tt> if the map is still empty. - */ - public long[][] getReference() - { - return levels; + return (index == -1) ? -1 : ((int) levelsRef[index][1]); } /** @@ -144,15 +120,14 @@ public class AudioLevelMap */ private int findCSRC(long[][] levels, long csrc) { - if( levels == null ) - return -1; - - for (int i = 0; i < levels.length; i++) + if (levels != null) { - if (levels [i][0] == csrc) - return i; + for (int i = 0; i < levels.length; i++) + { + if (levels[i][0] == csrc) + return i; + } } - return -1; } @@ -172,30 +147,16 @@ public class AudioLevelMap */ private long[][] appendCSRCToMatrix(long[][] levels, long csrc, int level) { - int newLength = 1; - - if( levels != null && levels.length > 0) - { - newLength = levels.length + 1; - } - - long[][] newLevels = new long[newLength][2]; + int newLength = 1 + ((levels == null) ? 0 : levels.length); + long[][] newLevels = new long[newLength][]; //put the new level. - newLevels[0][0] = csrc; - newLevels[0][1] = level; + newLevels[0] = new long[] { csrc, level }; - if( newLength == 1) + if (newLength == 1) return newLevels; - for (int i = 0; i < levels.length; i ++) - { - //csrc - newLevels[i+1][0] = levels [i][0]; - - //level - newLevels[i+1][1] = levels [i][1]; - } + System.arraycopy(levels, 0, newLevels, 1, levels.length); return newLevels; } 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 2d92cfa..8343145 100644 --- a/src/net/java/sip/communicator/impl/neomedia/device/AudioMixerMediaDevice.java +++ b/src/net/java/sip/communicator/impl/neomedia/device/AudioMixerMediaDevice.java @@ -119,7 +119,7 @@ public class AudioMixerMediaDevice */ private final Map<ReceiveStream, AudioLevelEventDispatcher> streamAudioLevelListeners - = new Hashtable<ReceiveStream, AudioLevelEventDispatcher>(); + = new HashMap<ReceiveStream, AudioLevelEventDispatcher>(); /** * Initializes a new <tt>AudioMixerMediaDevice</tt> instance which is to @@ -278,7 +278,7 @@ public class AudioMixerMediaDevice */ synchronized(localUserAudioLevelListeners) { - if (localUserAudioLevelListeners.size() == 0) + if (localUserAudioLevelListeners.isEmpty()) return; } @@ -462,9 +462,8 @@ public class AudioMixerMediaDevice { //if this is the first listener that we are seeing then we also //need to create the dispatcher. - if (localUserAudioLevelListeners.size() == 0) + if (localUserAudioLevelListeners.isEmpty()) { - localUserAudioLevelDispatcher .setAudioLevelListener(localUserAudioLevelDelegator); @@ -577,15 +576,15 @@ public class AudioMixerMediaDevice * from <tt>stream</tt>. */ public void putStreamAudioLevelListener( - ReceiveStream stream, - SimpleAudioLevelListener listener) + ReceiveStream stream, + SimpleAudioLevelListener listener) { synchronized(streamAudioLevelListeners) { AudioLevelEventDispatcher dispatcher = streamAudioLevelListeners.get(stream); - if ( dispatcher == null ) + if (dispatcher == null) { //this is not a replacement but a registration for a stream //that was not listened to so far. create it and "put" it @@ -606,7 +605,7 @@ public class AudioMixerMediaDevice * @param l the listener we'd like to remove. */ public void removeLocalUserAudioLevelListener( - SimpleAudioLevelListener l) + SimpleAudioLevelListener l) { synchronized(localUserAudioLevelListeners) { @@ -629,10 +628,9 @@ public class AudioMixerMediaDevice //if this was the last listener then we also need to remove the //dispatcher - if (localUserAudioLevelListeners.size() == 0) + if (localUserAudioLevelListeners.isEmpty()) { localUserAudioLevelDispatcher.stop(); - localUserAudioLevelDispatcher.setAudioLevelListener(null); } } @@ -948,6 +946,7 @@ public class AudioMixerMediaDevice * * @param processor the processor. */ + @Override protected void registerLocalUserAudioLevelEffect(Processor processor) { } @@ -1032,8 +1031,9 @@ public class AudioMixerMediaDevice @Override public int getLastMeasuredAudioLevel(long csrc) { - return ((AudioMixerMediaDevice)getDevice()) - .audioLevelCache.getLevel(csrc); + return + ((AudioMixerMediaDevice) getDevice()).audioLevelCache.getLevel( + csrc); } /** @@ -1045,8 +1045,9 @@ public class AudioMixerMediaDevice @Override public int getLastMeasuredLocalUserAudioLevel() { - return ((AudioMixerMediaDevice)getDevice()) - .lastMeasuredLocalUserAudioLevel; + return + ((AudioMixerMediaDevice) getDevice()) + .lastMeasuredLocalUserAudioLevel; } /** diff --git a/src/net/java/sip/communicator/impl/neomedia/transform/csrc/CsrcTransformEngine.java b/src/net/java/sip/communicator/impl/neomedia/transform/csrc/CsrcTransformEngine.java index f5fe4da..80ef4e7 100644 --- a/src/net/java/sip/communicator/impl/neomedia/transform/csrc/CsrcTransformEngine.java +++ b/src/net/java/sip/communicator/impl/neomedia/transform/csrc/CsrcTransformEngine.java @@ -218,17 +218,19 @@ public class CsrcTransformEngine byte[] extensionBuff = getExtensionBuff(buffLen); - extensionBuff[0] = - (byte)((csrcAudioLevelExtID << 4) | (csrcList.length - 1)); + extensionBuff[0] + = (byte)((csrcAudioLevelExtID << 4) | (csrcList.length - 1)); int csrcOffset = 1; // initial offset is equal to ext hdr size for(long csrc : csrcList) { - byte level = (byte)((AudioMediaStreamImpl)mediaStream) - .getLastMeasuredAudioLevel(csrc); - extensionBuff[csrcOffset] = level; + byte level + = (byte) + ((AudioMediaStreamImpl)mediaStream) + .getLastMeasuredAudioLevel(csrc); + extensionBuff[csrcOffset] = level; csrcOffset ++; } |