1363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang/*
2363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Copyright (C) 2010 The Android Open Source Project
3363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang *
4363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Licensed under the Apache License, Version 2.0 (the "License");
5363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * you may not use this file except in compliance with the License.
6363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * You may obtain a copy of the License at
7363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang *
8363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang *      http://www.apache.org/licenses/LICENSE-2.0
9363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang *
10363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Unless required by applicable law or agreed to in writing, software
11363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * distributed under the License is distributed on an "AS IS" BASIS,
12363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * See the License for the specific language governing permissions and
14363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * limitations under the License.
15363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */
16363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
17363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangpackage android.net.rtp;
18363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
1932e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yehimport java.util.Arrays;
2032e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh
2132e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh/**
2232e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * This class defines a collection of audio codecs to be used with
2332e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * {@link AudioStream}s. Their parameters are designed to be exchanged using
2432e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * Session Description Protocol (SDP). Most of the values listed here can be
2532e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * found in RFC 3551, while others are described in separated standards.
2632e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh *
2732e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * <p>Few simple configurations are defined as public static instances for the
2832e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * convenience of direct uses. More complicated ones could be obtained using
2932e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * {@link #getCodec(int, String, String)}. For example, one can use the
3032e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * following snippet to create a mode-1-only AMR codec.</p>
3132e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * <pre>
3232e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * AudioCodec codec = AudioCodec.getCodec(100, "AMR/8000", "mode-set=1");
3332e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * </pre>
3432e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh *
3532e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * @see AudioStream
3632e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh */
37363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangpublic class AudioCodec {
3832e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh    /**
3932e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * The RTP payload type of the encoding.
4032e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     */
4132e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh    public final int type;
4232e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh
4332e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh    /**
4432e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * The encoding parameters to be used in the corresponding SDP attribute.
4532e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     */
4632e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh    public final String rtpmap;
4732e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh
4832e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh    /**
4932e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * The format parameters to be used in the corresponding SDP attribute.
5032e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     */
5132e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh    public final String fmtp;
5232e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh
5332e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh    /**
5432e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * G.711 u-law audio codec.
5532e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     */
5632e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh    public static final AudioCodec PCMU = new AudioCodec(0, "PCMU/8000", null);
5732e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh
5832e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh    /**
5932e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * G.711 a-law audio codec.
6032e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     */
6132e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh    public static final AudioCodec PCMA = new AudioCodec(8, "PCMA/8000", null);
62363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
63363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    /**
6432e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * GSM Full-Rate audio codec, also known as GSM-FR, GSM 06.10, GSM, or
6532e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * simply FR.
66363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     */
6732e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh    public static final AudioCodec GSM = new AudioCodec(3, "GSM/8000", null);
6832e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh
6932e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh    /**
7032e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * GSM Enhanced Full-Rate audio codec, also known as GSM-EFR, GSM 06.60, or
7132e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * simply EFR.
7232e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     */
7332e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh    public static final AudioCodec GSM_EFR = new AudioCodec(96, "GSM-EFR/8000", null);
7432e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh
7532e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh    /**
7632e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * Adaptive Multi-Rate narrowband audio codec, also known as AMR or AMR-NB.
7732e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * Currently CRC, robust sorting, and interleaving are not supported. See
7832e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * more details about these features in RFC 4867.
7932e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     */
8032e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh    public static final AudioCodec AMR = new AudioCodec(97, "AMR/8000", null);
8132e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh
82f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh    private static final AudioCodec[] sCodecs = {GSM_EFR, AMR, GSM, PCMU, PCMA};
8332e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh
8432e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh    private AudioCodec(int type, String rtpmap, String fmtp) {
8532e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh        this.type = type;
8632e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh        this.rtpmap = rtpmap;
8732e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh        this.fmtp = fmtp;
88363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    }
89363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
90363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    /**
9132e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * Returns system supported audio codecs.
9232e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     */
9332e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh    public static AudioCodec[] getCodecs() {
9432e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh        return Arrays.copyOf(sCodecs, sCodecs.length);
9532e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh    }
9632e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh
9732e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh    /**
9832e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * Creates an AudioCodec according to the given configuration.
99363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     *
10032e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * @param type The payload type of the encoding defined in RTP/AVP.
10132e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * @param rtpmap The encoding parameters specified in the corresponding SDP
10232e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     *     attribute, or null if it is not available.
10332e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * @param fmtp The format parameters specified in the corresponding SDP
10432e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     *     attribute, or null if it is not available.
10532e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * @return The configured AudioCodec or {@code null} if it is not supported.
106363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     */
10732e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh    public static AudioCodec getCodec(int type, String rtpmap, String fmtp) {
10832e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh        if (type < 0 || type > 127) {
10932e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh            return null;
110363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        }
111363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
11232e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh        AudioCodec hint = null;
11332e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh        if (rtpmap != null) {
11432e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh            String clue = rtpmap.trim().toUpperCase();
11532e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh            for (AudioCodec codec : sCodecs) {
11632e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh                if (clue.startsWith(codec.rtpmap)) {
11732e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh                    String channels = clue.substring(codec.rtpmap.length());
11832e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh                    if (channels.length() == 0 || channels.equals("/1")) {
11932e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh                        hint = codec;
12032e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh                    }
12132e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh                    break;
12232e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh                }
12332e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh            }
12432e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh        } else if (type < 96) {
12532e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh            for (AudioCodec codec : sCodecs) {
12632e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh                if (type == codec.type) {
12732e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh                    hint = codec;
12832e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh                    rtpmap = codec.rtpmap;
12932e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh                    break;
13032e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh                }
13132e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh            }
13232e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh        }
133363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
13432e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh        if (hint == null) {
13532e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh            return null;
13632e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh        }
13732e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh        if (hint == AMR && fmtp != null) {
13832e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh            String clue = fmtp.toLowerCase();
13932e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh            if (clue.contains("crc=1") || clue.contains("robust-sorting=1") ||
14032e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh                    clue.contains("interleaving=")) {
14132e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh                return null;
14232e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh            }
14332e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh        }
14432e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh        return new AudioCodec(type, rtpmap, fmtp);
145363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    }
146363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang}
147