aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Dittmann <wernerd@java.net>2010-05-11 16:44:30 +0000
committerWerner Dittmann <wernerd@java.net>2010-05-11 16:44:30 +0000
commit1ce520313bbb1ebf3038795f73dda2299036e658 (patch)
treed2cc4a1c1642e26977b7b4b4f95a348605fe4711
parentc2bcedcf6aaaa8d1851b356ac01d7f770ee72e49 (diff)
downloadjitsi-1ce520313bbb1ebf3038795f73dda2299036e658.zip
jitsi-1ce520313bbb1ebf3038795f73dda2299036e658.tar.gz
jitsi-1ce520313bbb1ebf3038795f73dda2299036e658.tar.bz2
Implement finer synchronization granularity for portaudio streams
Use dedicated syncronization object in InputStream and MasterStream to implement a synchronization policy with finer granularity. This speeds up processing if SC uses several InputStream, for example several calls that are not on hold.
-rw-r--r--src/net/java/sip/communicator/impl/neomedia/portaudio/streams/InputPortAudioStream.java72
-rw-r--r--src/net/java/sip/communicator/impl/neomedia/portaudio/streams/MasterPortAudioStream.java50
2 files changed, 82 insertions, 40 deletions
diff --git a/src/net/java/sip/communicator/impl/neomedia/portaudio/streams/InputPortAudioStream.java b/src/net/java/sip/communicator/impl/neomedia/portaudio/streams/InputPortAudioStream.java
index adaaadd..8d49647 100644
--- a/src/net/java/sip/communicator/impl/neomedia/portaudio/streams/InputPortAudioStream.java
+++ b/src/net/java/sip/communicator/impl/neomedia/portaudio/streams/InputPortAudioStream.java
@@ -66,6 +66,7 @@ public class InputPortAudioStream
this.parentStream = parentStream;
}
+ private Object readSync = new Object();
/**
* Reads audio data from this <tt>InputPortAudioStream</tt> into a specific
* <tt>Buffer</tt> blocking until audio data is indeed available.
@@ -82,41 +83,53 @@ public class InputPortAudioStream
buffer.setLength(0);
return;
}
-
- synchronized (parentStream)
+
+ synchronized (readSync)
{
- if (bufferData == null)
- {
- parentStream.read(buffer);
- }
- else
+ while (true)
{
- /*
- * If buffer conatins a data area then check if the type and
- * length fits. If yes then use it, otherwise allocate a new
- * area and set it in buffer.
- *
- * In case we can re-use the data area: copy the data, don't
- * just set the bufferData into buffer because bufferData
- * points to a data area in another buffer instance.
- */
- Object data = buffer.getData();
- byte[] tmpArray;
- if (data instanceof byte[] && ((byte[])data).length >= bufferLength) {
- tmpArray = (byte[])data;
+ if (bufferData == null) {
+ // parent read returns false if read is already active, wait
+ // until notified by setBuffer below.
+ if (!parentStream.read(buffer)) {
+ try {
+ readSync.wait();
+ } catch (InterruptedException e) {
+ continue;
+ }
+ continue; // bufferData was set by setBuffer
+ }
+ // parent read returned true, break loop below
}
else
{
- tmpArray = new byte[bufferLength];
- buffer.setData(tmpArray);
+ /*
+ * If buffer conatins a data area then check if the type and
+ * length fits. If yes then use it, otherwise allocate a new
+ * area and set it in buffer.
+ *
+ * In case we can re-use the data area: copy the data, don't
+ * just set the bufferData into buffer because bufferData
+ * points to a data area in another buffer instance.
+ */
+ Object data = buffer.getData();
+ byte[] tmpArray;
+ if (data instanceof byte[] && ((byte[])data).length >= bufferLength) {
+ tmpArray = (byte[])data;
+ }
+ else
+ {
+ tmpArray = new byte[bufferLength];
+ buffer.setData(tmpArray);
+ }
+ System.arraycopy(bufferData, 0, tmpArray, 0, bufferLength);
+ buffer.setFlags(Buffer.FLAG_SYSTEM_TIME);
+ buffer.setLength(bufferLength);
+ buffer.setOffset(0);
+ buffer.setTimeStamp(bufferTimeStamp);
}
- System.arraycopy(bufferData, 0, tmpArray, 0, bufferLength);
- buffer.setFlags(Buffer.FLAG_SYSTEM_TIME);
- buffer.setLength(bufferLength);
- buffer.setOffset(0);
- buffer.setTimeStamp(bufferTimeStamp);
+ break;
}
-
/*
* The bufferData of this InputPortAudioStream has been consumed so
* make sure a new piece of audio data will be read the next time.
@@ -142,11 +155,12 @@ public class InputPortAudioStream
*/
void setBuffer(byte[] bufferData, int bufferLength, long bufferTimeStamp)
{
- synchronized (parentStream)
+ synchronized (readSync)
{
this.bufferData = bufferData;
this.bufferLength = bufferLength;
this.bufferTimeStamp = bufferTimeStamp;
+ readSync.notifyAll();
}
}
diff --git a/src/net/java/sip/communicator/impl/neomedia/portaudio/streams/MasterPortAudioStream.java b/src/net/java/sip/communicator/impl/neomedia/portaudio/streams/MasterPortAudioStream.java
index 7b51a3e..7ad3a28 100644
--- a/src/net/java/sip/communicator/impl/neomedia/portaudio/streams/MasterPortAudioStream.java
+++ b/src/net/java/sip/communicator/impl/neomedia/portaudio/streams/MasterPortAudioStream.java
@@ -80,6 +80,10 @@ public class MasterPortAudioStream
private long stream = 0;
/**
+ * Whether a read is active.
+ */
+ private boolean readActive = false;
+ /**
* Creates new stream.
* @param deviceIndex the device to use.
* @param channels the channels to serve.
@@ -144,6 +148,8 @@ public class MasterPortAudioStream
null);
}
+ private Object readSync = new Object();
+
/**
* Reads audio data from this <tt>MasterPortAudioStream</tt> into a specific
* <tt>Buffer</tt> blocking until audio data is indeed available.
@@ -151,14 +157,21 @@ public class MasterPortAudioStream
* @param buffer the <tt>Buffer</tt> into which the audio data read from
* this <tt>MasterPortAudioStream</tt> is to be returned
* @throws PortAudioException if an error occurs while reading
- */
- public synchronized void read(Buffer buffer)
+ */
+ public boolean read(Buffer buffer)
throws PortAudioException
{
- if (!started)
- {
- buffer.setLength(0);
- return;
+ synchronized (readSync) {
+ if (readActive)
+ {
+ return false;
+ }
+ readActive = true;
+ if (!started)
+ {
+ buffer.setLength(0);
+ return true;
+ }
}
/*
@@ -197,6 +210,11 @@ public class MasterPortAudioStream
.get(slaveIndex)
.setBuffer(bufferData, bytesPerBuffer, bufferTimeStamp);
}
+ synchronized(readSync) {
+ readActive = false;
+ readSync.notify();
+ }
+ return true;
}
/**
@@ -281,11 +299,21 @@ public class MasterPortAudioStream
if(slaves.isEmpty())
{
- // stop
- PortAudio.Pa_CloseStream(stream);
- stream = 0;
- started = false;
- PortAudioManager.getInstance().stoppedInputPortAudioStream(this);
+ synchronized (readSync) {
+ while (readActive)
+ {
+ try {
+ readSync.wait();
+ } catch (InterruptedException e) {
+ continue;
+ }
+ }
+ // stop
+ PortAudio.Pa_CloseStream(stream);
+ stream = 0;
+ started = false;
+ PortAudioManager.getInstance().stoppedInputPortAudioStream(this);
+ }
}
}
}