1 /*
2  * Copyright (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 package android.net.rtp;
18 
19 import java.util.Arrays;
20 
21 /**
22  * This class defines a collection of audio codecs to be used with
23  * {@link AudioStream}s. Their parameters are designed to be exchanged using
24  * Session Description Protocol (SDP). Most of the values listed here can be
25  * found in RFC 3551, while others are described in separated standards.
26  *
27  * <p>Few simple configurations are defined as public static instances for the
28  * convenience of direct uses. More complicated ones could be obtained using
29  * {@link #getCodec(int, String, String)}. For example, one can use the
30  * following snippet to create a mode-1-only AMR codec.</p>
31  * <pre>
32  * AudioCodec codec = AudioCodec.getCodec(100, "AMR/8000", "mode-set=1");
33  * </pre>
34  *
35  * @see AudioStream
36  */
37 public class AudioCodec {
38     /**
39      * The RTP payload type of the encoding.
40      */
41     public final int type;
42 
43     /**
44      * The encoding parameters to be used in the corresponding SDP attribute.
45      */
46     public final String rtpmap;
47 
48     /**
49      * The format parameters to be used in the corresponding SDP attribute.
50      */
51     public final String fmtp;
52 
53     /**
54      * G.711 u-law audio codec.
55      */
56     public static final AudioCodec PCMU = new AudioCodec(0, "PCMU/8000", null);
57 
58     /**
59      * G.711 a-law audio codec.
60      */
61     public static final AudioCodec PCMA = new AudioCodec(8, "PCMA/8000", null);
62 
63     /**
64      * GSM Full-Rate audio codec, also known as GSM-FR, GSM 06.10, GSM, or
65      * simply FR.
66      */
67     public static final AudioCodec GSM = new AudioCodec(3, "GSM/8000", null);
68 
69     /**
70      * GSM Enhanced Full-Rate audio codec, also known as GSM-EFR, GSM 06.60, or
71      * simply EFR.
72      */
73     public static final AudioCodec GSM_EFR = new AudioCodec(96, "GSM-EFR/8000", null);
74 
75     /**
76      * Adaptive Multi-Rate narrowband audio codec, also known as AMR or AMR-NB.
77      * Currently CRC, robust sorting, and interleaving are not supported. See
78      * more details about these features in RFC 4867.
79      */
80     public static final AudioCodec AMR = new AudioCodec(97, "AMR/8000", null);
81 
82     private static final AudioCodec[] sCodecs = {GSM_EFR, AMR, GSM, PCMU, PCMA};
83 
AudioCodec(int type, String rtpmap, String fmtp)84     private AudioCodec(int type, String rtpmap, String fmtp) {
85         this.type = type;
86         this.rtpmap = rtpmap;
87         this.fmtp = fmtp;
88     }
89 
90     /**
91      * Returns system supported audio codecs.
92      */
getCodecs()93     public static AudioCodec[] getCodecs() {
94         return Arrays.copyOf(sCodecs, sCodecs.length);
95     }
96 
97     /**
98      * Creates an AudioCodec according to the given configuration.
99      *
100      * @param type The payload type of the encoding defined in RTP/AVP.
101      * @param rtpmap The encoding parameters specified in the corresponding SDP
102      *     attribute, or null if it is not available.
103      * @param fmtp The format parameters specified in the corresponding SDP
104      *     attribute, or null if it is not available.
105      * @return The configured AudioCodec or {@code null} if it is not supported.
106      */
getCodec(int type, String rtpmap, String fmtp)107     public static AudioCodec getCodec(int type, String rtpmap, String fmtp) {
108         if (type < 0 || type > 127) {
109             return null;
110         }
111 
112         AudioCodec hint = null;
113         if (rtpmap != null) {
114             String clue = rtpmap.trim().toUpperCase();
115             for (AudioCodec codec : sCodecs) {
116                 if (clue.startsWith(codec.rtpmap)) {
117                     String channels = clue.substring(codec.rtpmap.length());
118                     if (channels.length() == 0 || channels.equals("/1")) {
119                         hint = codec;
120                     }
121                     break;
122                 }
123             }
124         } else if (type < 96) {
125             for (AudioCodec codec : sCodecs) {
126                 if (type == codec.type) {
127                     hint = codec;
128                     rtpmap = codec.rtpmap;
129                     break;
130                 }
131             }
132         }
133 
134         if (hint == null) {
135             return null;
136         }
137         if (hint == AMR && fmtp != null) {
138             String clue = fmtp.toLowerCase();
139             if (clue.contains("crc=1") || clue.contains("robust-sorting=1") ||
140                     clue.contains("interleaving=")) {
141                 return null;
142             }
143         }
144         return new AudioCodec(type, rtpmap, fmtp);
145     }
146 }
147