Loading voip/java/android/net/rtp/AudioGroup.java +77 −33 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 { Loading Loading @@ -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; Loading @@ -93,6 +100,15 @@ public class AudioGroup { mStreams = new HashMap<AudioStream, Integer>(); } /** * 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. */ Loading @@ -108,18 +124,27 @@ public class AudioGroup { * @param mode The mode to change to. * @throws IllegalArgumentException if the mode is invalid. */ public synchronized native void setMode(int mode); public void setMode(int mode) { if (mode < 0 || mode > MODE_LAST) { throw new IllegalArgumentException("Invalid mode"); } synchronized (this) { nativeSetMode(mode); mMode = mode; } } private native void add(int mode, int socket, String remoteAddress, int remotePort, String codecSpec, int dtmfType); private native void nativeSetMode(int mode); synchronized void add(AudioStream stream, AudioCodec codec, int dtmfType) { // 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); add(stream.getMode(), socket, nativeAdd(stream.getMode(), socket, stream.getRemoteAddress().getHostAddress(), stream.getRemotePort(), codecSpec, dtmfType); mStreams.put(stream, socket); Loading @@ -128,15 +153,22 @@ public class AudioGroup { } } } } 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) { // Package-private method used by AudioStream.join(). void remove(AudioStream stream) { synchronized (this) { Integer socket = mStreams.remove(stream); if (socket != null) { remove(socket); nativeRemove(socket); } } } private native void nativeRemove(int socket); /** * Sends a DTMF digit to every {@link AudioStream} in this group. Currently Loading @@ -144,13 +176,25 @@ public class AudioGroup { * * @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 Loading voip/java/android/net/rtp/AudioStream.java +17 −11 Original line number Diff line number Diff line Loading @@ -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 */ Loading Loading @@ -82,6 +86,7 @@ public class AudioStream extends RtpStream { * @see AudioGroup */ public void join(AudioGroup group) { synchronized (this) { if (mGroup == group) { return; } Loading @@ -94,6 +99,7 @@ public class AudioStream extends RtpStream { mGroup = group; } } } /** * Returns the {@link AudioCodec}, or {@code null} if it is not set. Loading voip/java/android/net/rtp/RtpStream.java +6 −1 Original line number Diff line number Diff line Loading @@ -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 { Loading @@ -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; Loading Loading @@ -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; Loading voip/jni/rtp/AmrCodec.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -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; Loading voip/jni/rtp/AudioGroup.cpp +6 −12 Original line number Diff line number Diff line Loading @@ -90,6 +90,7 @@ public: void encode(int tick, AudioStream *chain); void decode(int tick); private: enum { NORMAL = 0, SEND_ONLY = 1, Loading @@ -97,7 +98,6 @@ public: LAST_MODE = 2, }; private: int mMode; int mSocket; sockaddr_storage mRemote; Loading Loading @@ -463,6 +463,7 @@ public: bool add(AudioStream *stream); bool remove(int socket); private: enum { ON_HOLD = 0, MUTED = 1, Loading @@ -471,7 +472,6 @@ public: LAST_MODE = 3, }; private: AudioStream *mChain; int mEventQueue; volatile int mDtmfEvent; Loading Loading @@ -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) Loading @@ -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 Loading Loading
voip/java/android/net/rtp/AudioGroup.java +77 −33 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 { Loading Loading @@ -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; Loading @@ -93,6 +100,15 @@ public class AudioGroup { mStreams = new HashMap<AudioStream, Integer>(); } /** * 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. */ Loading @@ -108,18 +124,27 @@ public class AudioGroup { * @param mode The mode to change to. * @throws IllegalArgumentException if the mode is invalid. */ public synchronized native void setMode(int mode); public void setMode(int mode) { if (mode < 0 || mode > MODE_LAST) { throw new IllegalArgumentException("Invalid mode"); } synchronized (this) { nativeSetMode(mode); mMode = mode; } } private native void add(int mode, int socket, String remoteAddress, int remotePort, String codecSpec, int dtmfType); private native void nativeSetMode(int mode); synchronized void add(AudioStream stream, AudioCodec codec, int dtmfType) { // 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); add(stream.getMode(), socket, nativeAdd(stream.getMode(), socket, stream.getRemoteAddress().getHostAddress(), stream.getRemotePort(), codecSpec, dtmfType); mStreams.put(stream, socket); Loading @@ -128,15 +153,22 @@ public class AudioGroup { } } } } 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) { // Package-private method used by AudioStream.join(). void remove(AudioStream stream) { synchronized (this) { Integer socket = mStreams.remove(stream); if (socket != null) { remove(socket); nativeRemove(socket); } } } private native void nativeRemove(int socket); /** * Sends a DTMF digit to every {@link AudioStream} in this group. Currently Loading @@ -144,13 +176,25 @@ public class AudioGroup { * * @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 Loading
voip/java/android/net/rtp/AudioStream.java +17 −11 Original line number Diff line number Diff line Loading @@ -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 */ Loading Loading @@ -82,6 +86,7 @@ public class AudioStream extends RtpStream { * @see AudioGroup */ public void join(AudioGroup group) { synchronized (this) { if (mGroup == group) { return; } Loading @@ -94,6 +99,7 @@ public class AudioStream extends RtpStream { mGroup = group; } } } /** * Returns the {@link AudioCodec}, or {@code null} if it is not set. Loading
voip/java/android/net/rtp/RtpStream.java +6 −1 Original line number Diff line number Diff line Loading @@ -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 { Loading @@ -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; Loading Loading @@ -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; Loading
voip/jni/rtp/AmrCodec.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -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; Loading
voip/jni/rtp/AudioGroup.cpp +6 −12 Original line number Diff line number Diff line Loading @@ -90,6 +90,7 @@ public: void encode(int tick, AudioStream *chain); void decode(int tick); private: enum { NORMAL = 0, SEND_ONLY = 1, Loading @@ -97,7 +98,6 @@ public: LAST_MODE = 2, }; private: int mMode; int mSocket; sockaddr_storage mRemote; Loading Loading @@ -463,6 +463,7 @@ public: bool add(AudioStream *stream); bool remove(int socket); private: enum { ON_HOLD = 0, MUTED = 1, Loading @@ -471,7 +472,6 @@ public: LAST_MODE = 3, }; private: AudioStream *mChain; int mEventQueue; volatile int mDtmfEvent; Loading Loading @@ -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) Loading @@ -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 Loading