• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyrightm (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <string.h>
18 
19 #include "AudioCodec.h"
20 
21 #include "gsmamr_dec.h"
22 #include "gsmamr_enc.h"
23 
24 namespace {
25 
26 const int gFrameBits[8] = {95, 103, 118, 134, 148, 159, 204, 244};
27 
28 //------------------------------------------------------------------------------
29 
30 // See RFC 4867 for the encoding details.
31 
32 class AmrCodec : public AudioCodec
33 {
34 public:
AmrCodec()35     AmrCodec() {
36         if (AMREncodeInit(&mEncoder, &mSidSync, false)) {
37             mEncoder = NULL;
38         }
39         if (GSMInitDecode(&mDecoder, (Word8 *)"RTP")) {
40             mDecoder = NULL;
41         }
42     }
43 
~AmrCodec()44     ~AmrCodec() {
45         if (mEncoder) {
46             AMREncodeExit(&mEncoder, &mSidSync);
47         }
48         if (mDecoder) {
49             GSMDecodeFrameExit(&mDecoder);
50         }
51     }
52 
53     int set(int sampleRate, const char *fmtp);
54     int encode(void *payload, int16_t *samples);
55     int decode(int16_t *samples, int count, void *payload, int length);
56 
57 private:
58     void *mEncoder;
59     void *mSidSync;
60     void *mDecoder;
61 
62     int mMode;
63     int mModeSet;
64     bool mOctetAligned;
65 };
66 
set(int sampleRate,const char * fmtp)67 int AmrCodec::set(int sampleRate, const char *fmtp)
68 {
69     // These parameters are not supported.
70     if (strcasestr(fmtp, "crc=1") || strcasestr(fmtp, "robust-sorting=1") ||
71         strcasestr(fmtp, "interleaving=")) {
72         return -1;
73     }
74 
75     // Handle mode-set and octet-align.
76     const char *modes = strcasestr(fmtp, "mode-set=");
77     if (modes) {
78         mMode = 0;
79         mModeSet = 0;
80         for (char c = *modes; c && c != ' '; c = *++modes) {
81             if (c >= '0' && c <= '7') {
82                 int mode = c - '0';
83                 if (mode > mMode) {
84                     mMode = mode;
85                 }
86                 mModeSet |= 1 << mode;
87             }
88         }
89     } else {
90         mMode = 7;
91         mModeSet = 0xFF;
92     }
93     mOctetAligned = (strcasestr(fmtp, "octet-align=1") != NULL);
94 
95     // TODO: handle mode-change-*.
96 
97     return (sampleRate == 8000 && mEncoder && mDecoder) ? 160 : -1;
98 }
99 
encode(void * payload,int16_t * samples)100 int AmrCodec::encode(void *payload, int16_t *samples)
101 {
102     unsigned char *bytes = (unsigned char *)payload;
103     Frame_Type_3GPP type;
104 
105     int length = AMREncode(mEncoder, mSidSync, (Mode)mMode,
106         samples, bytes + 1, &type, AMR_TX_WMF);
107 
108     if (type != mMode || length != (8 + gFrameBits[mMode] + 7) >> 3) {
109         return -1;
110     }
111 
112     if (mOctetAligned) {
113         bytes[0] = 0xF0;
114         bytes[1] = (mMode << 3) | 0x04;
115         ++length;
116     } else {
117         // CMR = 15 (4-bit), F = 0 (1-bit), FT = mMode (4-bit), Q = 1 (1-bit).
118         bytes[0] = 0xFF;
119         bytes[1] = 0xC0 | (mMode << 1) | 1;
120 
121         // Shift left 6 bits and update the length.
122         bytes[length + 1] = 0;
123         for (int i = 0; i <= length; ++i) {
124             bytes[i] = (bytes[i] << 6) | (bytes[i + 1] >> 2);
125         }
126         length = (10 + gFrameBits[mMode] + 7) >> 3;
127     }
128     return length;
129 }
130 
decode(int16_t * samples,int,void * payload,int length)131 int AmrCodec::decode(int16_t *samples, int /* count */, void *payload, int length)
132 {
133     unsigned char *bytes = (unsigned char *)payload;
134     Frame_Type_3GPP type;
135     if (length < 2) {
136         return -1;
137     }
138     int request = bytes[0] >> 4;
139 
140     if (mOctetAligned) {
141         if ((bytes[1] & 0xC4) != 0x04) {
142             return -1;
143         }
144         type = (Frame_Type_3GPP)(bytes[1] >> 3);
145         if (length != (16 + gFrameBits[type] + 7) >> 3) {
146             return -1;
147         }
148         length -= 2;
149         bytes += 2;
150     } else {
151         if ((bytes[0] & 0x0C) || !(bytes[1] & 0x40)) {
152             return -1;
153         }
154         type = (Frame_Type_3GPP)((bytes[0] << 1 | bytes[1] >> 7) & 0x07);
155         if (length != (10 + gFrameBits[type] + 7) >> 3) {
156             return -1;
157         }
158 
159         // Shift left 2 bits and update the length.
160         --length;
161         for (int i = 1; i < length; ++i) {
162             bytes[i] = (bytes[i] << 2) | (bytes[i + 1] >> 6);
163         }
164         bytes[length] <<= 2;
165         length = (gFrameBits[type] + 7) >> 3;
166         ++bytes;
167     }
168 
169     if (AMRDecode(mDecoder, type, bytes, samples, MIME_IETF) != length) {
170         return -1;
171     }
172 
173     // Handle CMR
174     if (request < 8 && request != mMode) {
175         for (int i = request; i >= 0; --i) {
176             if (mModeSet & (1 << i)) {
177                 mMode = request;
178                 break;
179             }
180         }
181     }
182 
183     return 160;
184 }
185 
186 //------------------------------------------------------------------------------
187 
188 // See RFC 3551 for the encoding details.
189 
190 class GsmEfrCodec : public AudioCodec
191 {
192 public:
GsmEfrCodec()193     GsmEfrCodec() {
194         if (AMREncodeInit(&mEncoder, &mSidSync, false)) {
195             mEncoder = NULL;
196         }
197         if (GSMInitDecode(&mDecoder, (Word8 *)"RTP")) {
198             mDecoder = NULL;
199         }
200     }
201 
~GsmEfrCodec()202     ~GsmEfrCodec() {
203         if (mEncoder) {
204             AMREncodeExit(&mEncoder, &mSidSync);
205         }
206         if (mDecoder) {
207             GSMDecodeFrameExit(&mDecoder);
208         }
209     }
210 
set(int sampleRate,const char *)211     int set(int sampleRate, const char */* fmtp */) {
212         return (sampleRate == 8000 && mEncoder && mDecoder) ? 160 : -1;
213     }
214 
215     int encode(void *payload, int16_t *samples);
216     int decode(int16_t *samples, int count, void *payload, int length);
217 
218 private:
219     void *mEncoder;
220     void *mSidSync;
221     void *mDecoder;
222 };
223 
encode(void * payload,int16_t * samples)224 int GsmEfrCodec::encode(void *payload, int16_t *samples)
225 {
226     unsigned char *bytes = (unsigned char *)payload;
227     Frame_Type_3GPP type;
228 
229     int length = AMREncode(mEncoder, mSidSync, MR122,
230         samples, bytes, &type, AMR_TX_WMF);
231 
232     if (type == AMR_122 && length == 32) {
233         bytes[0] = 0xC0 | (bytes[1] >> 4);
234         for (int i = 1; i < 31; ++i) {
235             bytes[i] = (bytes[i] << 4) | (bytes[i + 1] >> 4);
236         }
237         return 31;
238     }
239     return -1;
240 }
241 
decode(int16_t * samples,int count,void * payload,int length)242 int GsmEfrCodec::decode(int16_t *samples, int count, void *payload, int length)
243 {
244     unsigned char *bytes = (unsigned char *)payload;
245     int n = 0;
246     while (n + 160 <= count && length >= 31 && (bytes[0] >> 4) == 0x0C) {
247         for (int i = 0; i < 30; ++i) {
248             bytes[i] = (bytes[i] << 4) | (bytes[i + 1] >> 4);
249         }
250         bytes[30] <<= 4;
251 
252         if (AMRDecode(mDecoder, AMR_122, bytes, &samples[n], MIME_IETF) != 31) {
253             break;
254         }
255         n += 160;
256         length -= 31;
257         bytes += 31;
258     }
259     return n;
260 }
261 
262 } // namespace
263 
newAmrCodec()264 AudioCodec *newAmrCodec()
265 {
266     return new AmrCodec;
267 }
268 
newGsmEfrCodec()269 AudioCodec *newGsmEfrCodec()
270 {
271     return new GsmEfrCodec;
272 }
273