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.net.InetAddress; 20 import java.net.SocketException; 21 22 /** 23 * An AudioStream is a {@link RtpStream} which carrys audio payloads over 24 * Real-time Transport Protocol (RTP). Two different classes are developed in 25 * order to support various usages such as audio conferencing. An AudioStream 26 * represents a remote endpoint which consists of a network mapping and a 27 * configured {@link AudioCodec}. On the other side, An {@link AudioGroup} 28 * represents a local endpoint which mixes all the AudioStreams and optionally 29 * interacts with the speaker and the microphone at the same time. The simplest 30 * usage includes one for each endpoints. For other combinations, developers 31 * should be aware of the limitations described in {@link AudioGroup}. 32 * 33 * <p>An AudioStream becomes busy when it joins an AudioGroup. In this case most 34 * of the setter methods are disabled. This is designed to ease the task of 35 * managing native resources. One can always make an AudioStream leave its 36 * AudioGroup by calling {@link #join(AudioGroup)} with {@code null} and put it 37 * back after the modification is done.</p> 38 * 39 * <p class="note">Using this class requires 40 * {@link android.Manifest.permission#INTERNET} permission.</p> 41 * 42 * @see RtpStream 43 * @see AudioGroup 44 */ 45 public class AudioStream extends RtpStream { 46 private AudioCodec mCodec; 47 private int mDtmfType = -1; 48 private AudioGroup mGroup; 49 50 /** 51 * Creates an AudioStream on the given local address. Note that the local 52 * port is assigned automatically to conform with RFC 3550. 53 * 54 * @param address The network address of the local host to bind to. 55 * @throws SocketException if the address cannot be bound or a problem 56 * occurs during binding. 57 */ AudioStream(InetAddress address)58 public AudioStream(InetAddress address) throws SocketException { 59 super(address); 60 } 61 62 /** 63 * Returns {@code true} if the stream has already joined an 64 * {@link AudioGroup}. 65 */ 66 @Override isBusy()67 public final boolean isBusy() { 68 return mGroup != null; 69 } 70 71 /** 72 * Returns the joined {@link AudioGroup}. 73 */ getGroup()74 public AudioGroup getGroup() { 75 return mGroup; 76 } 77 78 /** 79 * Joins an {@link AudioGroup}. Each stream can join only one group at a 80 * time. The group can be changed by passing a different one or removed 81 * by calling this method with {@code null}. 82 * 83 * @param group The AudioGroup to join or {@code null} to leave. 84 * @throws IllegalStateException if the stream is not properly configured. 85 * @see AudioGroup 86 */ join(AudioGroup group)87 public void join(AudioGroup group) { 88 synchronized (this) { 89 if (mGroup == group) { 90 return; 91 } 92 if (mGroup != null) { 93 mGroup.remove(this); 94 mGroup = null; 95 } 96 if (group != null) { 97 group.add(this); 98 mGroup = group; 99 } 100 } 101 } 102 103 /** 104 * Returns the {@link AudioCodec}, or {@code null} if it is not set. 105 * 106 * @see #setCodec(AudioCodec) 107 */ getCodec()108 public AudioCodec getCodec() { 109 return mCodec; 110 } 111 112 /** 113 * Sets the {@link AudioCodec}. 114 * 115 * @param codec The AudioCodec to be used. 116 * @throws IllegalArgumentException if its type is used by DTMF. 117 * @throws IllegalStateException if the stream is busy. 118 */ setCodec(AudioCodec codec)119 public void setCodec(AudioCodec codec) { 120 if (isBusy()) { 121 throw new IllegalStateException("Busy"); 122 } 123 if (codec.type == mDtmfType) { 124 throw new IllegalArgumentException("The type is used by DTMF"); 125 } 126 mCodec = codec; 127 } 128 129 /** 130 * Returns the RTP payload type for dual-tone multi-frequency (DTMF) digits, 131 * or {@code -1} if it is not enabled. 132 * 133 * @see #setDtmfType(int) 134 */ getDtmfType()135 public int getDtmfType() { 136 return mDtmfType; 137 } 138 139 /** 140 * Sets the RTP payload type for dual-tone multi-frequency (DTMF) digits. 141 * The primary usage is to send digits to the remote gateway to perform 142 * certain tasks, such as second-stage dialing. According to RFC 2833, the 143 * RTP payload type for DTMF is assigned dynamically, so it must be in the 144 * range of 96 and 127. One can use {@code -1} to disable DTMF and free up 145 * the previous assigned type. This method cannot be called when the stream 146 * already joined an {@link AudioGroup}. 147 * 148 * @param type The RTP payload type to be used or {@code -1} to disable it. 149 * @throws IllegalArgumentException if the type is invalid or used by codec. 150 * @throws IllegalStateException if the stream is busy. 151 * @see AudioGroup#sendDtmf(int) 152 */ setDtmfType(int type)153 public void setDtmfType(int type) { 154 if (isBusy()) { 155 throw new IllegalStateException("Busy"); 156 } 157 if (type != -1) { 158 if (type < 96 || type > 127) { 159 throw new IllegalArgumentException("Invalid type"); 160 } 161 if (mCodec != null && type == mCodec.type) { 162 throw new IllegalArgumentException("The type is used by codec"); 163 } 164 } 165 mDtmfType = type; 166 } 167 } 168