AudioStream.java revision 32e106b7bdd57c82ee67705871f6116d92bce79b
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 19363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangimport java.net.InetAddress; 20363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangimport java.net.SocketException; 21363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 22363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang/** 2332e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * An AudioStream is a {@link RtpStream} which carrys audio payloads over 2432e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * Real-time Transport Protocol (RTP). Two different classes are developed in 2532e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * order to support various usages such as audio conferencing. An AudioStream 2632e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * represents a remote endpoint which consists of a network mapping and a 2732e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * configured {@link AudioCodec}. On the other side, An {@link AudioGroup} 2832e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * represents a local endpoint which mixes all the AudioStreams and optionally 2932e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * interacts with the speaker and the microphone at the same time. The simplest 3032e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * usage includes one for each endpoints. For other combinations, users should 3132e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * be aware of the limitations described in {@link AudioGroup}. 3232e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * 3332e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * <p>An AudioStream becomes busy when it joins an AudioGroup. In this case most 3432e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * of the setter methods are disabled. This is designed to ease the task of 3532e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * managing native resources. One can always make an AudioStream leave its 3632e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * AudioGroup by calling {@link #join(AudioGroup)} with {@code null} and put it 3732e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * back after the modification is done. 3832e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * 3932e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * @see AudioGroup 4032e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * @hide 41363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 42363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangpublic class AudioStream extends RtpStream { 43363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang private AudioCodec mCodec; 44363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang private int mDtmfType = -1; 45363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang private AudioGroup mGroup; 46363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 47363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 48363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Creates an AudioStream on the given local address. Note that the local 49363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * port is assigned automatically to conform with RFC 3550. 50363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 51363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param address The network address of the local host to bind to. 52363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @throws SocketException if the address cannot be bound or a problem 53363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * occurs during binding. 54363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 55363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public AudioStream(InetAddress address) throws SocketException { 56363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang super(address); 57363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 58363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 59363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 6032e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * Returns {@code true} if the stream has already joined an 6132e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * {@link AudioGroup}. 62363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 63363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang @Override 64363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public final boolean isBusy() { 65363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang return mGroup != null; 66363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 67363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 68363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 69363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Returns the joined {@link AudioGroup}. 70363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 7132e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh public AudioGroup getGroup() { 72363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang return mGroup; 73363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 74363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 75363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 76363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Joins an {@link AudioGroup}. Each stream can join only one group at a 77363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * time. The group can be changed by passing a different one or removed 78363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * by calling this method with {@code null}. 79363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 80363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param group The AudioGroup to join or {@code null} to leave. 81363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @throws IllegalStateException if the stream is not properly configured. 82363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @see AudioGroup 83363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 84363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public void join(AudioGroup group) { 85363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang if (mGroup == group) { 86363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang return; 87363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 88363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang if (mGroup != null) { 89363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang mGroup.remove(this); 90363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang mGroup = null; 91363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 92363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang if (group != null) { 9332e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh group.add(this, mCodec, mDtmfType); 94363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang mGroup = group; 95363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 96363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 97363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 98363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 9932e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * Sets the {@link AudioCodec}. 100363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 101363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param codec The AudioCodec to be used. 10232e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * @throws IllegalArgumentException if its type is used by DTMF. 103363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @throws IllegalStateException if the stream is busy. 104363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 10532e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh public void setCodec(AudioCodec codec) { 106363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang if (isBusy()) { 107363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throw new IllegalStateException("Busy"); 108363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 10932e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh if (codec.type == mDtmfType) { 110363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throw new IllegalArgumentException("The type is used by DTMF"); 111363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 112363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang mCodec = codec; 113363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 114363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 115363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 116363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Sets the RTP payload type for dual-tone multi-frequency (DTMF) digits. 117363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * The primary usage is to send digits to the remote gateway to perform 118363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * certain tasks, such as second-stage dialing. According to RFC 2833, the 119363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * RTP payload type for DTMF is assigned dynamically, so it must be in the 120363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * range of 96 and 127. One can use {@code -1} to disable DTMF and free up 121363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * the previous assigned value. This method cannot be called when the stream 122363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * already joined an {@link AudioGroup}. 123363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 124363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param type The RTP payload type to be used or {@code -1} to disable it. 125363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @throws IllegalArgumentException if the type is invalid or used by codec. 126363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @throws IllegalStateException if the stream is busy. 127363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @see AudioGroup#sendDtmf(int) 128363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 129363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public void setDtmfType(int type) { 130363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang if (isBusy()) { 131363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throw new IllegalStateException("Busy"); 132363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 133363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang if (type != -1) { 134363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang if (type < 96 || type > 127) { 135363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throw new IllegalArgumentException("Invalid type"); 136363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 13732e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh if (type == mCodec.type) { 138363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throw new IllegalArgumentException("The type is used by codec"); 139363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 140363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 141363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang mDtmfType = type; 142363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 143363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang} 144