RTP: support payloads with larger packetization interval.
RFC 3551 section 4.2 said that a receiver should accept packets
representing between 0 and 200ms of audio data. Now we add the
ability to decode multiple frames in a payload as long as the
jitter buffer is not full. This change covers G711, GSM, and
GSM-EFR. AMR will be added later.
Bug: 3029736
Change-Id: Ifd194596766d14f02177925c58432cd620e44dd7
diff --git a/jni/rtp/AmrCodec.cpp b/jni/rtp/AmrCodec.cpp
index 84c7166..e2d820e 100644
--- a/jni/rtp/AmrCodec.cpp
+++ b/jni/rtp/AmrCodec.cpp
@@ -52,7 +52,7 @@
int set(int sampleRate, const char *fmtp);
int encode(void *payload, int16_t *samples);
- int decode(int16_t *samples, void *payload, int length);
+ int decode(int16_t *samples, int count, void *payload, int length);
private:
void *mEncoder;
@@ -128,7 +128,7 @@
return length;
}
-int AmrCodec::decode(int16_t *samples, void *payload, int length)
+int AmrCodec::decode(int16_t *samples, int count, void *payload, int length)
{
unsigned char *bytes = (unsigned char *)payload;
Frame_Type_3GPP type;
@@ -213,7 +213,7 @@
}
int encode(void *payload, int16_t *samples);
- int decode(int16_t *samples, void *payload, int length);
+ int decode(int16_t *samples, int count, void *payload, int length);
private:
void *mEncoder;
@@ -239,20 +239,24 @@
return -1;
}
-int GsmEfrCodec::decode(int16_t *samples, void *payload, int length)
+int GsmEfrCodec::decode(int16_t *samples, int count, void *payload, int length)
{
unsigned char *bytes = (unsigned char *)payload;
- if (length == 31 && (bytes[0] >> 4) == 0x0C) {
+ int n = 0;
+ while (n + 160 <= count && length >= 31 && (bytes[0] >> 4) == 0x0C) {
for (int i = 0; i < 30; ++i) {
bytes[i] = (bytes[i] << 4) | (bytes[i + 1] >> 4);
}
bytes[30] <<= 4;
- if (AMRDecode(mDecoder, AMR_122, bytes, samples, MIME_IETF) == 31) {
- return 160;
+ if (AMRDecode(mDecoder, AMR_122, bytes, &samples[n], MIME_IETF) != 31) {
+ break;
}
+ n += 160;
+ length -= 31;
+ bytes += 31;
}
- return -1;
+ return n;
}
} // namespace
diff --git a/jni/rtp/AudioCodec.h b/jni/rtp/AudioCodec.h
index e389255..741730b 100644
--- a/jni/rtp/AudioCodec.h
+++ b/jni/rtp/AudioCodec.h
@@ -30,7 +30,7 @@
// Returns the length of payload in bytes.
virtual int encode(void *payload, int16_t *samples) = 0;
// Returns the number of decoded samples.
- virtual int decode(int16_t *samples, void *payload, int length) = 0;
+ virtual int decode(int16_t *samples, int count, void *payload, int length) = 0;
};
AudioCodec *newAudioCodec(const char *codecName);
diff --git a/jni/rtp/AudioGroup.cpp b/jni/rtp/AudioGroup.cpp
index 529b425..9b0455c 100644
--- a/jni/rtp/AudioGroup.cpp
+++ b/jni/rtp/AudioGroup.cpp
@@ -395,7 +395,8 @@
mLatencyTimer = tick;
}
- if (mBufferTail - mBufferHead > BUFFER_SIZE - mInterval) {
+ int count = (BUFFER_SIZE - (mBufferTail - mBufferHead)) * mSampleRate;
+ if (count < mSampleCount) {
// Buffer overflow. Drop the packet.
LOGV("stream[%d] buffer overflow", mSocket);
recv(mSocket, &c, 1, MSG_DONTWAIT);
@@ -403,19 +404,18 @@
}
// Receive the packet and decode it.
- int16_t samples[mSampleCount];
- int length = 0;
+ int16_t samples[count];
if (!mCodec) {
// Special case for device stream.
- length = recv(mSocket, samples, sizeof(samples),
+ count = recv(mSocket, samples, sizeof(samples),
MSG_TRUNC | MSG_DONTWAIT) >> 1;
} else {
__attribute__((aligned(4))) uint8_t buffer[2048];
sockaddr_storage remote;
- socklen_t len = sizeof(remote);
+ socklen_t addrlen = sizeof(remote);
- length = recvfrom(mSocket, buffer, sizeof(buffer),
- MSG_TRUNC | MSG_DONTWAIT, (sockaddr *)&remote, &len);
+ int length = recvfrom(mSocket, buffer, sizeof(buffer),
+ MSG_TRUNC | MSG_DONTWAIT, (sockaddr *)&remote, &addrlen);
// Do we need to check SSRC, sequence, and timestamp? They are not
// reliable but at least they can be used to identify duplicates?
@@ -433,14 +433,15 @@
}
length -= offset;
if (length >= 0) {
- length = mCodec->decode(samples, &buffer[offset], length);
+ length = mCodec->decode(samples, count, &buffer[offset], length);
}
if (length > 0 && mFixRemote) {
mRemote = remote;
mFixRemote = false;
}
+ count = length;
}
- if (length <= 0) {
+ if (count <= 0) {
LOGV("stream[%d] decoder error", mSocket);
return;
}
@@ -462,7 +463,7 @@
// Append to the jitter buffer.
int tail = mBufferTail * mSampleRate;
- for (int i = 0; i < mSampleCount; ++i) {
+ for (int i = 0; i < count; ++i) {
mBuffer[tail & mBufferMask] = samples[i];
++tail;
}
diff --git a/jni/rtp/G711Codec.cpp b/jni/rtp/G711Codec.cpp
index a467acf..ef54863 100644
--- a/jni/rtp/G711Codec.cpp
+++ b/jni/rtp/G711Codec.cpp
@@ -39,7 +39,7 @@
return mSampleCount;
}
int encode(void *payload, int16_t *samples);
- int decode(int16_t *samples, void *payload, int length);
+ int decode(int16_t *samples, int count, void *payload, int length);
private:
int mSampleCount;
};
@@ -64,9 +64,12 @@
return mSampleCount;
}
-int UlawCodec::decode(int16_t *samples, void *payload, int length)
+int UlawCodec::decode(int16_t *samples, int count, void *payload, int length)
{
int8_t *ulaws = (int8_t *)payload;
+ if (length > count) {
+ length = count;
+ }
for (int i = 0; i < length; ++i) {
int ulaw = ~ulaws[i];
int exponent = (ulaw >> 4) & 0x07;
@@ -87,7 +90,7 @@
return mSampleCount;
}
int encode(void *payload, int16_t *samples);
- int decode(int16_t *samples, void *payload, int length);
+ int decode(int16_t *samples, int count, void *payload, int length);
private:
int mSampleCount;
};
@@ -111,9 +114,12 @@
return mSampleCount;
}
-int AlawCodec::decode(int16_t *samples, void *payload, int length)
+int AlawCodec::decode(int16_t *samples, int count, void *payload, int length)
{
int8_t *alaws = (int8_t *)payload;
+ if (length > count) {
+ length = count;
+ }
for (int i = 0; i < length; ++i) {
int alaw = alaws[i] ^ 0x55;
int exponent = (alaw >> 4) & 0x07;
diff --git a/jni/rtp/GsmCodec.cpp b/jni/rtp/GsmCodec.cpp
index 8d2286e..61dfdc9 100644
--- a/jni/rtp/GsmCodec.cpp
+++ b/jni/rtp/GsmCodec.cpp
@@ -44,7 +44,7 @@
}
int encode(void *payload, int16_t *samples);
- int decode(int16_t *samples, void *payload, int length);
+ int decode(int16_t *samples, int count, void *payload, int length);
private:
gsm mEncode;
@@ -57,13 +57,17 @@
return 33;
}
-int GsmCodec::decode(int16_t *samples, void *payload, int length)
+int GsmCodec::decode(int16_t *samples, int count, void *payload, int length)
{
- if (length == 33 &&
- gsm_decode(mDecode, (unsigned char *)payload, samples) == 0) {
- return 160;
+ unsigned char *bytes = (unsigned char *)payload;
+ int n = 0;
+ while (n + 160 <= count && length >= 33 &&
+ gsm_decode(mDecode, bytes, &samples[n]) == 0) {
+ n += 160;
+ length -= 33;
+ bytes += 33;
}
- return -1;
+ return n;
}
} // namespace