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
24namespace {
25
26const int gFrameBits[8] = {95, 103, 118, 134, 148, 159, 204, 244};
27
28//------------------------------------------------------------------------------
29
30// See RFC 4867 for the encoding details.
31
32class AmrCodec : public AudioCodec
33{
34public:
35    AmrCodec() {
36        if (AMREncodeInit(&mEncoder, &mSidSync, false)) {
37            mEncoder = NULL;
38        }
39        if (GSMInitDecode(&mDecoder, (Word8 *)"RTP")) {
40            mDecoder = NULL;
41        }
42    }
43
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
57private:
58    void *mEncoder;
59    void *mSidSync;
60    void *mDecoder;
61
62    int mMode;
63    int mModeSet;
64    bool mOctetAligned;
65};
66
67int 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
100int 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
131int 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
190class GsmEfrCodec : public AudioCodec
191{
192public:
193    GsmEfrCodec() {
194        if (AMREncodeInit(&mEncoder, &mSidSync, false)) {
195            mEncoder = NULL;
196        }
197        if (GSMInitDecode(&mDecoder, (Word8 *)"RTP")) {
198            mDecoder = NULL;
199        }
200    }
201
202    ~GsmEfrCodec() {
203        if (mEncoder) {
204            AMREncodeExit(&mEncoder, &mSidSync);
205        }
206        if (mDecoder) {
207            GSMDecodeFrameExit(&mDecoder);
208        }
209    }
210
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
218private:
219    void *mEncoder;
220    void *mSidSync;
221    void *mDecoder;
222};
223
224int 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
242int 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
264AudioCodec *newAmrCodec()
265{
266    return new AmrCodec;
267}
268
269AudioCodec *newGsmEfrCodec()
270{
271    return new GsmEfrCodec;
272}
273