diff options
author | Chia-chi Yeh <chiachi@android.com> | 2011-09-06 14:18:37 -0700 |
---|---|---|
committer | Chia-chi Yeh <chiachi@android.com> | 2011-09-06 14:34:44 -0700 |
commit | 35d05dcba1e829782813b6ec21afceb5cffc22e6 (patch) | |
tree | 4f5287ebc5edea42a12ff4f772c5574f57cf2542 /voip | |
parent | 1ed7a407fafe50b1eb0878f560bb0618706e4e82 (diff) | |
download | frameworks_base-35d05dcba1e829782813b6ec21afceb5cffc22e6.zip frameworks_base-35d05dcba1e829782813b6ec21afceb5cffc22e6.tar.gz frameworks_base-35d05dcba1e829782813b6ec21afceb5cffc22e6.tar.bz2 |
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
Diffstat (limited to 'voip')
-rw-r--r-- | voip/jni/rtp/AmrCodec.cpp | 20 | ||||
-rw-r--r-- | voip/jni/rtp/AudioCodec.h | 2 | ||||
-rw-r--r-- | voip/jni/rtp/AudioGroup.cpp | 21 | ||||
-rw-r--r-- | voip/jni/rtp/G711Codec.cpp | 14 | ||||
-rw-r--r-- | voip/jni/rtp/GsmCodec.cpp | 16 |
5 files changed, 44 insertions, 29 deletions
diff --git a/voip/jni/rtp/AmrCodec.cpp b/voip/jni/rtp/AmrCodec.cpp index 84c7166..e2d820e 100644 --- a/voip/jni/rtp/AmrCodec.cpp +++ b/voip/jni/rtp/AmrCodec.cpp @@ -52,7 +52,7 @@ public: 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 @@ int AmrCodec::encode(void *payload, int16_t *samples) 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 @@ public: } 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 @@ int GsmEfrCodec::encode(void *payload, int16_t *samples) 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/voip/jni/rtp/AudioCodec.h b/voip/jni/rtp/AudioCodec.h index e389255..741730b 100644 --- a/voip/jni/rtp/AudioCodec.h +++ b/voip/jni/rtp/AudioCodec.h @@ -30,7 +30,7 @@ public: // 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/voip/jni/rtp/AudioGroup.cpp b/voip/jni/rtp/AudioGroup.cpp index 529b425..9b0455c 100644 --- a/voip/jni/rtp/AudioGroup.cpp +++ b/voip/jni/rtp/AudioGroup.cpp @@ -395,7 +395,8 @@ void AudioStream::decode(int tick) 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 @@ void AudioStream::decode(int tick) } // 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 @@ void AudioStream::decode(int tick) } 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 @@ void AudioStream::decode(int tick) // 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/voip/jni/rtp/G711Codec.cpp b/voip/jni/rtp/G711Codec.cpp index a467acf..ef54863 100644 --- a/voip/jni/rtp/G711Codec.cpp +++ b/voip/jni/rtp/G711Codec.cpp @@ -39,7 +39,7 @@ public: 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 @@ int UlawCodec::encode(void *payload, int16_t *samples) 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 @@ public: 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 @@ int AlawCodec::encode(void *payload, int16_t *samples) 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/voip/jni/rtp/GsmCodec.cpp b/voip/jni/rtp/GsmCodec.cpp index 8d2286e..61dfdc9 100644 --- a/voip/jni/rtp/GsmCodec.cpp +++ b/voip/jni/rtp/GsmCodec.cpp @@ -44,7 +44,7 @@ public: } 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 @@ int GsmCodec::encode(void *payload, int16_t *samples) 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 |