diff options
author | Chia-chi Yeh <chiachi@android.com> | 2010-11-30 13:10:31 +0800 |
---|---|---|
committer | Chia-chi Yeh <chiachi@android.com> | 2010-12-01 11:35:51 +0800 |
commit | 53aa6ef70d8692277f9403f94d43918ad9712dd0 (patch) | |
tree | 838ec2bb2c5154da687cb01a6cfa1e6449ab8e0c /voip | |
parent | 1318af1a476bb39b80fcadf5e545856aa2e90de2 (diff) | |
download | frameworks_base-53aa6ef70d8692277f9403f94d43918ad9712dd0.zip frameworks_base-53aa6ef70d8692277f9403f94d43918ad9712dd0.tar.gz frameworks_base-53aa6ef70d8692277f9403f94d43918ad9712dd0.tar.bz2 |
RTP: Prepare to unhide the APIs.
Polish things a little bit.
Change-Id: I2c3cea8b34b9c858879bc722ea1f38082ba22b8d
Diffstat (limited to 'voip')
-rw-r--r-- | voip/java/android/net/rtp/AudioGroup.java | 110 | ||||
-rw-r--r-- | voip/java/android/net/rtp/AudioStream.java | 28 | ||||
-rw-r--r-- | voip/java/android/net/rtp/RtpStream.java | 7 | ||||
-rw-r--r-- | voip/jni/rtp/AmrCodec.cpp | 2 | ||||
-rw-r--r-- | voip/jni/rtp/AudioGroup.cpp | 18 |
5 files changed, 107 insertions, 58 deletions
diff --git a/voip/java/android/net/rtp/AudioGroup.java b/voip/java/android/net/rtp/AudioGroup.java index 43a3827..a6b54d8 100644 --- a/voip/java/android/net/rtp/AudioGroup.java +++ b/voip/java/android/net/rtp/AudioGroup.java @@ -21,14 +21,14 @@ import java.util.Map; /** * An AudioGroup acts as a router connected to the speaker, the microphone, and - * {@link AudioStream}s. Its pipeline has four steps. First, for each - * AudioStream not in {@link RtpStream#MODE_SEND_ONLY}, decodes its incoming - * packets and stores in its buffer. Then, if the microphone is enabled, - * processes the recorded audio and stores in its buffer. Third, if the speaker - * is enabled, mixes and playbacks buffers of all AudioStreams. Finally, for - * each AudioStream not in {@link RtpStream#MODE_RECEIVE_ONLY}, mixes all other - * buffers and sends back the encoded packets. An AudioGroup does nothing if - * there is no AudioStream in it. + * {@link AudioStream}s. Its execution loop consists of four steps. First, for + * each AudioStream not in {@link RtpStream#MODE_SEND_ONLY}, decodes its + * incoming packets and stores in its buffer. Then, if the microphone is + * enabled, processes the recorded audio and stores in its buffer. Third, if the + * speaker is enabled, mixes and playbacks buffers of all AudioStreams. Finally, + * for each AudioStream not in {@link RtpStream#MODE_RECEIVE_ONLY}, mixes all + * other buffers and sends back the encoded packets. An AudioGroup does nothing + * if there is no AudioStream in it. * * <p>Few things must be noticed before using these classes. The performance is * highly related to the system load and the network bandwidth. Usually a @@ -47,7 +47,12 @@ import java.util.Map; * modes other than {@link #MODE_ON_HOLD}. In addition, before adding an * AudioStream into an AudioGroup, one should always put all other AudioGroups * into {@link #MODE_ON_HOLD}. That will make sure the audio driver correctly - * initialized. + * initialized.</p> + * + * <p class="note">Using this class requires + * {@link android.Manifest.permission#RECORD_AUDIO} permission.</p> + * + * @see AudioStream * @hide */ public class AudioGroup { @@ -78,6 +83,8 @@ public class AudioGroup { */ public static final int MODE_ECHO_SUPPRESSION = 3; + private static final int MODE_LAST = 3; + private final Map<AudioStream, Integer> mStreams; private int mMode = MODE_ON_HOLD; @@ -94,6 +101,15 @@ public class AudioGroup { } /** + * Returns the {@link AudioStream}s in this group. + */ + public AudioStream[] getStreams() { + synchronized (this) { + return mStreams.keySet().toArray(new AudioStream[mStreams.size()]); + } + } + + /** * Returns the current mode. */ public int getMode() { @@ -108,49 +124,77 @@ public class AudioGroup { * @param mode The mode to change to. * @throws IllegalArgumentException if the mode is invalid. */ - public synchronized native void setMode(int mode); - - private native void add(int mode, int socket, String remoteAddress, - int remotePort, String codecSpec, int dtmfType); + public void setMode(int mode) { + if (mode < 0 || mode > MODE_LAST) { + throw new IllegalArgumentException("Invalid mode"); + } + synchronized (this) { + nativeSetMode(mode); + mMode = mode; + } + } - synchronized void add(AudioStream stream, AudioCodec codec, int dtmfType) { - if (!mStreams.containsKey(stream)) { - try { - int socket = stream.dup(); - String codecSpec = String.format("%d %s %s", codec.type, - codec.rtpmap, codec.fmtp); - add(stream.getMode(), socket, - stream.getRemoteAddress().getHostAddress(), - stream.getRemotePort(), codecSpec, dtmfType); - mStreams.put(stream, socket); - } catch (NullPointerException e) { - throw new IllegalStateException(e); + private native void nativeSetMode(int mode); + + // Package-private method used by AudioStream.join(). + void add(AudioStream stream, AudioCodec codec, int dtmfType) { + synchronized (this) { + if (!mStreams.containsKey(stream)) { + try { + int socket = stream.dup(); + String codecSpec = String.format("%d %s %s", codec.type, + codec.rtpmap, codec.fmtp); + nativeAdd(stream.getMode(), socket, + stream.getRemoteAddress().getHostAddress(), + stream.getRemotePort(), codecSpec, dtmfType); + mStreams.put(stream, socket); + } catch (NullPointerException e) { + throw new IllegalStateException(e); + } } } } - private native void remove(int socket); + private native void nativeAdd(int mode, int socket, String remoteAddress, + int remotePort, String codecSpec, int dtmfType); - synchronized void remove(AudioStream stream) { - Integer socket = mStreams.remove(stream); - if (socket != null) { - remove(socket); + // Package-private method used by AudioStream.join(). + void remove(AudioStream stream) { + synchronized (this) { + Integer socket = mStreams.remove(stream); + if (socket != null) { + nativeRemove(socket); + } } } + private native void nativeRemove(int socket); + /** * Sends a DTMF digit to every {@link AudioStream} in this group. Currently * only event {@code 0} to {@code 15} are supported. * * @throws IllegalArgumentException if the event is invalid. */ - public native synchronized void sendDtmf(int event); + public void sendDtmf(int event) { + if (event < 0 || event > 15) { + throw new IllegalArgumentException("Invalid event"); + } + synchronized (this) { + nativeSendDtmf(event); + } + } + + private native void nativeSendDtmf(int event); /** * Removes every {@link AudioStream} in this group. */ - public synchronized void clear() { - remove(-1); + public void clear() { + synchronized (this) { + mStreams.clear(); + nativeRemove(-1); + } } @Override diff --git a/voip/java/android/net/rtp/AudioStream.java b/voip/java/android/net/rtp/AudioStream.java index e5197ce..0edae6b 100644 --- a/voip/java/android/net/rtp/AudioStream.java +++ b/voip/java/android/net/rtp/AudioStream.java @@ -34,8 +34,12 @@ import java.net.SocketException; * of the setter methods are disabled. This is designed to ease the task of * managing native resources. One can always make an AudioStream leave its * AudioGroup by calling {@link #join(AudioGroup)} with {@code null} and put it - * back after the modification is done. + * back after the modification is done.</p> * + * <p class="note">Using this class requires + * {@link android.Manifest.permission#INTERNET} permission.</p> + * + * @see RtpStream * @see AudioGroup * @hide */ @@ -82,16 +86,18 @@ public class AudioStream extends RtpStream { * @see AudioGroup */ public void join(AudioGroup group) { - if (mGroup == group) { - return; - } - if (mGroup != null) { - mGroup.remove(this); - mGroup = null; - } - if (group != null) { - group.add(this, mCodec, mDtmfType); - mGroup = group; + synchronized (this) { + if (mGroup == group) { + return; + } + if (mGroup != null) { + mGroup.remove(this); + mGroup = null; + } + if (group != null) { + group.add(this, mCodec, mDtmfType); + mGroup = group; + } } } diff --git a/voip/java/android/net/rtp/RtpStream.java b/voip/java/android/net/rtp/RtpStream.java index 23fb258..87d8bc6 100644 --- a/voip/java/android/net/rtp/RtpStream.java +++ b/voip/java/android/net/rtp/RtpStream.java @@ -24,6 +24,9 @@ import java.net.SocketException; /** * RtpStream represents the base class of streams which send and receive network * packets with media payloads over Real-time Transport Protocol (RTP). + * + * <p class="note">Using this class requires + * {@link android.Manifest.permission#INTERNET} permission.</p> * @hide */ public class RtpStream { @@ -43,6 +46,8 @@ public class RtpStream { */ public static final int MODE_RECEIVE_ONLY = 2; + private static final int MODE_LAST = 2; + private final InetAddress mLocalAddress; private final int mLocalPort; @@ -129,7 +134,7 @@ public class RtpStream { if (isBusy()) { throw new IllegalStateException("Busy"); } - if (mode != MODE_NORMAL && mode != MODE_SEND_ONLY && mode != MODE_RECEIVE_ONLY) { + if (mode < 0 || mode > MODE_LAST) { throw new IllegalArgumentException("Invalid mode"); } mMode = mode; diff --git a/voip/jni/rtp/AmrCodec.cpp b/voip/jni/rtp/AmrCodec.cpp index 72ee44e..84c7166 100644 --- a/voip/jni/rtp/AmrCodec.cpp +++ b/voip/jni/rtp/AmrCodec.cpp @@ -73,7 +73,7 @@ int AmrCodec::set(int sampleRate, const char *fmtp) } // Handle mode-set and octet-align. - char *modes = (char*)strcasestr(fmtp, "mode-set="); + const char *modes = strcasestr(fmtp, "mode-set="); if (modes) { mMode = 0; mModeSet = 0; diff --git a/voip/jni/rtp/AudioGroup.cpp b/voip/jni/rtp/AudioGroup.cpp index 0c8a725..cba1123 100644 --- a/voip/jni/rtp/AudioGroup.cpp +++ b/voip/jni/rtp/AudioGroup.cpp @@ -90,6 +90,7 @@ public: void encode(int tick, AudioStream *chain); void decode(int tick); +private: enum { NORMAL = 0, SEND_ONLY = 1, @@ -97,7 +98,6 @@ public: LAST_MODE = 2, }; -private: int mMode; int mSocket; sockaddr_storage mRemote; @@ -463,6 +463,7 @@ public: bool add(AudioStream *stream); bool remove(int socket); +private: enum { ON_HOLD = 0, MUTED = 1, @@ -471,7 +472,6 @@ public: LAST_MODE = 3, }; -private: AudioStream *mChain; int mEventQueue; volatile int mDtmfEvent; @@ -948,16 +948,10 @@ void remove(JNIEnv *env, jobject thiz, jint socket) void setMode(JNIEnv *env, jobject thiz, jint mode) { - if (mode < 0 || mode > AudioGroup::LAST_MODE) { - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); - return; - } AudioGroup *group = (AudioGroup *)env->GetIntField(thiz, gNative); if (group && !group->setMode(mode)) { jniThrowException(env, "java/lang/IllegalArgumentException", NULL); - return; } - env->SetIntField(thiz, gMode, mode); } void sendDtmf(JNIEnv *env, jobject thiz, jint event) @@ -969,10 +963,10 @@ void sendDtmf(JNIEnv *env, jobject thiz, jint event) } JNINativeMethod gMethods[] = { - {"add", "(IILjava/lang/String;ILjava/lang/String;I)V", (void *)add}, - {"remove", "(I)V", (void *)remove}, - {"setMode", "(I)V", (void *)setMode}, - {"sendDtmf", "(I)V", (void *)sendDtmf}, + {"nativeAdd", "(IILjava/lang/String;ILjava/lang/String;I)V", (void *)add}, + {"nativeRemove", "(I)V", (void *)remove}, + {"nativeSetMode", "(I)V", (void *)setMode}, + {"nativeSendDtmf", "(I)V", (void *)sendDtmf}, }; } // namespace |