Home | History | Annotate | Download | only in rtp
      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:
     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 
     57 private:
     58     void *mEncoder;
     59     void *mSidSync;
     60     void *mDecoder;
     61 
     62     int mMode;
     63     int mModeSet;
     64     bool mOctetAligned;
     65 };
     66 
     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 
    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 
    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:
    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 
    218 private:
    219     void *mEncoder;
    220     void *mSidSync;
    221     void *mDecoder;
    222 };
    223 
    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 
    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 
    264 AudioCodec *newAmrCodec()
    265 {
    266     return new AmrCodec;
    267 }
    268 
    269 AudioCodec *newGsmEfrCodec()
    270 {
    271     return new GsmEfrCodec;
    272 }
    273