summaryrefslogtreecommitdiffstats
path: root/voip
diff options
context:
space:
mode:
authorChia-chi Yeh <chiachi@android.com>2010-08-24 13:58:12 +0800
committerChia-chi Yeh <chiachi@android.com>2010-08-24 13:58:12 +0800
commit2880ef86e5210832ef44f2d45c46ada1891372e5 (patch)
tree2b9136b9dcab61263b0747b45657764e74b62efc /voip
parentb80e610b070c2cec98a228a8aec450dc24a5f90a (diff)
downloadframeworks_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.cpp81
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;
}