diff --git a/src/org/jitsi/impl/neomedia/jmfext/media/protocol/wasapi/AudioCaptureClient.java b/src/org/jitsi/impl/neomedia/jmfext/media/protocol/wasapi/AudioCaptureClient.java index 06722ef21283976ba27679c73cb5bcdc5879a681..1778a82dc99339d5e1130be47826f50d4528a8d1 100644 --- a/src/org/jitsi/impl/neomedia/jmfext/media/protocol/wasapi/AudioCaptureClient.java +++ b/src/org/jitsi/impl/neomedia/jmfext/media/protocol/wasapi/AudioCaptureClient.java @@ -40,6 +40,24 @@ public class AudioCaptureClient private static final Logger logger = Logger.getLogger(AudioCaptureClient.class); + private static int maybeIAudioCaptureClientGetNextPacketSize( + long iAudioCaptureClient) + { + int numFramesInNextPacket; + + try + { + numFramesInNextPacket + = IAudioCaptureClient_GetNextPacketSize(iAudioCaptureClient); + } + catch (HResultException hre) + { + numFramesInNextPacket = 0; // Silence the compiler. + logger.error("IAudioCaptureClient_GetNextPacketSize", hre); + } + return numFramesInNextPacket; + } + /** * The internal buffer of this instance in which audio data is read from the * associated <tt>IAudioCaptureClient</tt> by the instance and awaits to be @@ -142,6 +160,17 @@ public class AudioCaptureClient */ final AudioFormat outFormat; + /** + * The indicator which reports whether audio samples have been read out of + * this instance since the indicator has been set to <tt>false</tt>. For + * example, determines whether audio samples have been read out of this + * instance since this instance has given control to its associated + * <tt>BufferTransferHandler</tt> (if any) and thus resolves a condition + * similar to a busy wait which arises if the associated + * <tt>BufferTransferHandler</tt> does not read any data. + */ + private boolean read; + /** * The number of channels with which {@link #iAudioClient} has been * initialized. @@ -505,6 +534,8 @@ else if (!started) { read = doRead(iMediaBuffer, buffer, offset, length); cause = null; + if (read > 0) + this.read = true; } catch (Throwable t) { @@ -556,18 +587,9 @@ private BufferTransferHandler readInEventHandleCmd() * Determine the size in bytes of the next data packet in the capture * endpoint buffer. */ - int numFramesInNextPacket; + int numFramesInNextPacket + = maybeIAudioCaptureClientGetNextPacketSize(iAudioCaptureClient); - try - { - numFramesInNextPacket - = IAudioCaptureClient_GetNextPacketSize(iAudioCaptureClient); - } - catch (HResultException hre) - { - numFramesInNextPacket = 0; // Silence the compiler. - logger.error("IAudioCaptureClient_GetNextPacketSize", hre); - } if (numFramesInNextPacket != 0) { int toRead = numFramesInNextPacket * dstFrameSize; @@ -619,6 +641,7 @@ private void runInEventHandleCmd(Runnable eventHandleCmd) { long eventHandle; BufferTransferHandler transferHandler; + int numFramesInNextPacket; synchronized (this) { @@ -648,6 +671,17 @@ private void runInEventHandleCmd(Runnable eventHandleCmd) try { transferHandler = readInEventHandleCmd(); + if (transferHandler != null) + read = false; + /* + * If the audio engine has more samples to deliver to the + * application, deliver them as soon as the transferHandler, + * if any, has been given a chance to read (from) the + * available samples. + */ + numFramesInNextPacket + = maybeIAudioCaptureClientGetNextPacketSize( + iAudioCaptureClient); } finally { @@ -668,7 +702,8 @@ private void runInEventHandleCmd(Runnable eventHandleCmd) * exception, we will WaitForSingleObject in order to * give the application time to recover. */ - continue; + if (read) + continue; } catch (Throwable t) { @@ -682,6 +717,12 @@ private void runInEventHandleCmd(Runnable eventHandleCmd) } } } + /* + * The audio engine may already have more samples to deliver to + * the application. + */ + if (numFramesInNextPacket != 0) + continue; int wfso; diff --git a/src/org/jitsi/impl/neomedia/jmfext/media/protocol/wasapi/WASAPIStream.java b/src/org/jitsi/impl/neomedia/jmfext/media/protocol/wasapi/WASAPIStream.java index 51b50143b3761a05bbd8f9f866526569cfe9bd6e..bdbb3d8504182b9d2563f557eb587329db0bd15b 100644 --- a/src/org/jitsi/impl/neomedia/jmfext/media/protocol/wasapi/WASAPIStream.java +++ b/src/org/jitsi/impl/neomedia/jmfext/media/protocol/wasapi/WASAPIStream.java @@ -1014,7 +1014,14 @@ private void initializeRender(final MediaLocator locator, AudioFormat format) * at this time. If the transferHandler (which will normally invoke * transferRenderData) was non-null, it would cause excessive CPU use. */ - BufferTransferHandler transferHandler = null; + BufferTransferHandler transferHandler + = new BufferTransferHandler() + { + public void transferData(PushBufferStream stream) + { + transferRenderData(); + } + }; render = new AudioCaptureClient( @@ -1022,7 +1029,7 @@ private void initializeRender(final MediaLocator locator, AudioFormat format) locator, AudioSystem.DataFlow.PLAYBACK, WASAPI.AUDCLNT_STREAMFLAGS_LOOPBACK, - /* hnsBufferDuration */ Format.NOT_SPECIFIED, + WASAPISystem.DEFAULT_BUFFER_DURATION, format, transferHandler); replenishRender = true; @@ -1115,7 +1122,7 @@ private void processInput(int dwInputStreamIndex, int maxLength) if ((dwInputStreamIndex == RENDER_INPUT_STREAM_INDEX) && replenishRender) { - int replenishThreshold = renderBufferMaxLength; + int replenishThreshold = (3 * renderBufferMaxLength / 2); if (audioCaptureClient.getAvailableLength() < replenishThreshold) @@ -1698,7 +1705,6 @@ private void transferCaptureData() * Notifies this instance that audio data has been made available in * {@link #render}. */ - @SuppressWarnings("unused") private void transferRenderData() { /*