diff options
author | Chia-chi Yeh <chiachi@android.com> | 2010-08-24 13:58:12 +0800 |
---|---|---|
committer | Chia-chi Yeh <chiachi@android.com> | 2010-08-24 13:58:12 +0800 |
commit | 2880ef86e5210832ef44f2d45c46ada1891372e5 (patch) | |
tree | 2b9136b9dcab61263b0747b45657764e74b62efc /voip | |
parent | b80e610b070c2cec98a228a8aec450dc24a5f90a (diff) | |
download | frameworks_base-2880ef86e5210832ef44f2d45c46ada1891372e5.zip frameworks_base-2880ef86e5210832ef44f2d45c46ada1891372e5.tar.gz frameworks_base-2880ef86e5210832ef44f2d45c46ada1891372e5.tar.bz2 |
RTP: reduce the latency by overlapping AudioRecord and AudioTrack.
Change-Id: I00d750ee514ef68d5b2a28bd1893417ed70ef1fc
Diffstat (limited to 'voip')
-rw-r--r-- | voip/jni/rtp/AudioGroup.cpp | 81 |
1 files changed, 53 insertions, 28 deletions
diff --git a/voip/jni/rtp/AudioGroup.cpp b/voip/jni/rtp/AudioGroup.cpp index 08a8d1c..bb45a9a 100644 --- a/voip/jni/rtp/AudioGroup.cpp +++ b/voip/jni/rtp/AudioGroup.cpp @@ -548,10 +548,11 @@ bool AudioGroup::set(int sampleRate, int sampleCount) } LOGD("reported frame count: output %d, input %d", output, input); - output = (output + sampleCount - 1) / sampleCount * sampleCount; - input = (input + sampleCount - 1) / sampleCount * sampleCount; - if (input < output * 2) { - input = output * 2; + if (output < sampleCount * 2) { + output = sampleCount * 2; + } + if (input < sampleCount * 2) { + input = sampleCount * 2; } LOGD("adjusted frame count: output %d, input %d", output, input); @@ -587,7 +588,7 @@ bool AudioGroup::set(int sampleRate, int sampleCount) // Give device socket a reasonable timeout and buffer size. timeval tv; tv.tv_sec = 0; - tv.tv_usec = 1000 * sampleCount / sampleRate * 500; + tv.tv_usec = 1000 * sampleCount / sampleRate * 1000; if (setsockopt(pair[0], SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) || setsockopt(pair[0], SOL_SOCKET, SO_RCVBUF, &output, sizeof(output)) || setsockopt(pair[1], SOL_SOCKET, SO_SNDBUF, &output, sizeof(output))) { @@ -764,38 +765,62 @@ bool AudioGroup::deviceLoop() if (recv(mDeviceSocket, output, sizeof(output), 0) <= 0) { memset(output, 0, sizeof(output)); } - if (mTrack.write(output, sizeof(output)) != (int)sizeof(output)) { - LOGE("cannot write to AudioTrack"); - return false; - } - if (mMode != MUTED) { - uint32_t frameCount = mRecord.frameCount(); - AudioRecord::Buffer input; - input.frameCount = frameCount; + int16_t input[mSampleCount]; + int toWrite = mSampleCount; + int toRead = (mMode == MUTED) ? 0 : mSampleCount; + int chances = 100; - if (mRecord.obtainBuffer(&input, -1) != NO_ERROR) { - LOGE("cannot read from AudioRecord"); - return false; - } + while (--chances > 0 && (toWrite > 0 || toRead > 0)) { + if (toWrite > 0) { + AudioTrack::Buffer buffer; + buffer.frameCount = toWrite; - if (input.frameCount < (uint32_t)mSampleCount) { - input.frameCount = 0; - } else { - if (mMode == NORMAL) { - send(mDeviceSocket, input.i8, sizeof(output), MSG_DONTWAIT); - } else { - // TODO: Echo canceller runs here. - send(mDeviceSocket, input.i8, sizeof(output), MSG_DONTWAIT); + status_t status = mTrack.obtainBuffer(&buffer, 1); + if (status == NO_ERROR) { + memcpy(buffer.i8, &output[mSampleCount - toWrite], buffer.size); + toWrite -= buffer.frameCount; + mTrack.releaseBuffer(&buffer); + } else if (status != TIMED_OUT && status != WOULD_BLOCK) { + LOGE("cannot write to AudioTrack"); + return false; } - if (input.frameCount < frameCount) { - input.frameCount = mSampleCount; + } + + if (toRead > 0) { + AudioRecord::Buffer buffer; + buffer.frameCount = mRecord.frameCount(); + + status_t status = mRecord.obtainBuffer(&buffer, 1); + if (status == NO_ERROR) { + int count = (buffer.frameCount < toRead) ? + buffer.frameCount : toRead; + memcpy(&input[mSampleCount - toRead], buffer.i8, count * 2); + toRead -= count; + if (buffer.frameCount < mRecord.frameCount()) { + buffer.frameCount = count; + } + mRecord.releaseBuffer(&buffer); + } else if (status != TIMED_OUT && status != WOULD_BLOCK) { + LOGE("cannot read from AudioRecord"); + return false; } } + } - mRecord.releaseBuffer(&input); + if (!chances) { + LOGE("device loop timeout"); + return false; } + if (mMode != MUTED) { + if (mMode == NORMAL) { + send(mDeviceSocket, input, sizeof(input), MSG_DONTWAIT); + } else { + // TODO: Echo canceller runs here. + send(mDeviceSocket, input, sizeof(input), MSG_DONTWAIT); + } + } return true; } |