Loading voip/java/android/net/rtp/AudioGroup.java +77 −33 Original line number Original line 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 * An AudioGroup acts as a router connected to the speaker, the microphone, and * {@link AudioStream}s. Its pipeline has four steps. First, for each * {@link AudioStream}s. Its execution loop consists of four steps. First, for * AudioStream not in {@link RtpStream#MODE_SEND_ONLY}, decodes its incoming * each AudioStream not in {@link RtpStream#MODE_SEND_ONLY}, decodes its * packets and stores in its buffer. Then, if the microphone is enabled, * incoming packets and stores in its buffer. Then, if the microphone is * processes the recorded audio and stores in its buffer. Third, if the speaker * enabled, processes the recorded audio and stores in its buffer. Third, if the * is enabled, mixes and playbacks buffers of all AudioStreams. Finally, for * speaker is enabled, mixes and playbacks buffers of all AudioStreams. Finally, * each AudioStream not in {@link RtpStream#MODE_RECEIVE_ONLY}, mixes all other * for each AudioStream not in {@link RtpStream#MODE_RECEIVE_ONLY}, mixes all * buffers and sends back the encoded packets. An AudioGroup does nothing if * other buffers and sends back the encoded packets. An AudioGroup does nothing * there is no AudioStream in it. * if there is no AudioStream in it. * * * <p>Few things must be noticed before using these classes. The performance is * <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 * 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 * modes other than {@link #MODE_ON_HOLD}. In addition, before adding an * AudioStream into an AudioGroup, one should always put all other AudioGroups * AudioStream into an AudioGroup, one should always put all other AudioGroups * into {@link #MODE_ON_HOLD}. That will make sure the audio driver correctly * 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 * @hide */ */ public class AudioGroup { public class AudioGroup { Loading Loading @@ -78,6 +83,8 @@ public class AudioGroup { */ */ public static final int MODE_ECHO_SUPPRESSION = 3; public static final int MODE_ECHO_SUPPRESSION = 3; private static final int MODE_LAST = 3; private final Map<AudioStream, Integer> mStreams; private final Map<AudioStream, Integer> mStreams; private int mMode = MODE_ON_HOLD; private int mMode = MODE_ON_HOLD; Loading @@ -93,6 +100,15 @@ public class AudioGroup { mStreams = new HashMap<AudioStream, Integer>(); 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. * Returns the current mode. */ */ Loading @@ -108,18 +124,27 @@ public class AudioGroup { * @param mode The mode to change to. * @param mode The mode to change to. * @throws IllegalArgumentException if the mode is invalid. * @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, private native void nativeSetMode(int mode); int remotePort, String codecSpec, int dtmfType); 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)) { if (!mStreams.containsKey(stream)) { try { try { int socket = stream.dup(); int socket = stream.dup(); String codecSpec = String.format("%d %s %s", codec.type, String codecSpec = String.format("%d %s %s", codec.type, codec.rtpmap, codec.fmtp); codec.rtpmap, codec.fmtp); add(stream.getMode(), socket, nativeAdd(stream.getMode(), socket, stream.getRemoteAddress().getHostAddress(), stream.getRemoteAddress().getHostAddress(), stream.getRemotePort(), codecSpec, dtmfType); stream.getRemotePort(), codecSpec, dtmfType); mStreams.put(stream, socket); 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); Integer socket = mStreams.remove(stream); if (socket != null) { 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 * 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. * @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. * Removes every {@link AudioStream} in this group. */ */ public synchronized void clear() { public void clear() { remove(-1); synchronized (this) { mStreams.clear(); nativeRemove(-1); } } } @Override @Override Loading voip/java/android/net/rtp/AudioStream.java +17 −11 Original line number Original line 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 * 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 * managing native resources. One can always make an AudioStream leave its * AudioGroup by calling {@link #join(AudioGroup)} with {@code null} and put it * 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 * @see AudioGroup * @hide * @hide */ */ Loading Loading @@ -82,6 +86,7 @@ public class AudioStream extends RtpStream { * @see AudioGroup * @see AudioGroup */ */ public void join(AudioGroup group) { public void join(AudioGroup group) { synchronized (this) { if (mGroup == group) { if (mGroup == group) { return; return; } } Loading @@ -94,6 +99,7 @@ public class AudioStream extends RtpStream { mGroup = group; mGroup = group; } } } } } /** /** * Returns the {@link AudioCodec}, or {@code null} if it is not set. * 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 Original line 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 * RtpStream represents the base class of streams which send and receive network * packets with media payloads over Real-time Transport Protocol (RTP). * 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 * @hide */ */ public class RtpStream { public class RtpStream { Loading @@ -43,6 +46,8 @@ public class RtpStream { */ */ public static final int MODE_RECEIVE_ONLY = 2; public static final int MODE_RECEIVE_ONLY = 2; private static final int MODE_LAST = 2; private final InetAddress mLocalAddress; private final InetAddress mLocalAddress; private final int mLocalPort; private final int mLocalPort; Loading Loading @@ -129,7 +134,7 @@ public class RtpStream { if (isBusy()) { if (isBusy()) { throw new IllegalStateException("Busy"); 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"); throw new IllegalArgumentException("Invalid mode"); } } mMode = mode; mMode = mode; Loading voip/jni/rtp/AmrCodec.cpp +1 −1 Original line number Original line Diff line number Diff line Loading @@ -73,7 +73,7 @@ int AmrCodec::set(int sampleRate, const char *fmtp) } } // Handle mode-set and octet-align. // Handle mode-set and octet-align. char *modes = (char*)strcasestr(fmtp, "mode-set="); const char *modes = strcasestr(fmtp, "mode-set="); if (modes) { if (modes) { mMode = 0; mMode = 0; mModeSet = 0; mModeSet = 0; Loading voip/jni/rtp/AudioGroup.cpp +6 −12 Original line number Original line Diff line number Diff line Loading @@ -90,6 +90,7 @@ public: void encode(int tick, AudioStream *chain); void encode(int tick, AudioStream *chain); void decode(int tick); void decode(int tick); private: enum { enum { NORMAL = 0, NORMAL = 0, SEND_ONLY = 1, SEND_ONLY = 1, Loading @@ -97,7 +98,6 @@ public: LAST_MODE = 2, LAST_MODE = 2, }; }; private: int mMode; int mMode; int mSocket; int mSocket; sockaddr_storage mRemote; sockaddr_storage mRemote; Loading Loading @@ -463,6 +463,7 @@ public: bool add(AudioStream *stream); bool add(AudioStream *stream); bool remove(int socket); bool remove(int socket); private: enum { enum { ON_HOLD = 0, ON_HOLD = 0, MUTED = 1, MUTED = 1, Loading @@ -471,7 +472,6 @@ public: LAST_MODE = 3, LAST_MODE = 3, }; }; private: AudioStream *mChain; AudioStream *mChain; int mEventQueue; int mEventQueue; volatile int mDtmfEvent; 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) 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); AudioGroup *group = (AudioGroup *)env->GetIntField(thiz, gNative); if (group && !group->setMode(mode)) { if (group && !group->setMode(mode)) { jniThrowException(env, "java/lang/IllegalArgumentException", NULL); jniThrowException(env, "java/lang/IllegalArgumentException", NULL); return; } } env->SetIntField(thiz, gMode, mode); } } void sendDtmf(JNIEnv *env, jobject thiz, jint event) void sendDtmf(JNIEnv *env, jobject thiz, jint event) Loading @@ -969,10 +963,10 @@ void sendDtmf(JNIEnv *env, jobject thiz, jint event) } } JNINativeMethod gMethods[] = { JNINativeMethod gMethods[] = { {"add", "(IILjava/lang/String;ILjava/lang/String;I)V", (void *)add}, {"nativeAdd", "(IILjava/lang/String;ILjava/lang/String;I)V", (void *)add}, {"remove", "(I)V", (void *)remove}, {"nativeRemove", "(I)V", (void *)remove}, {"setMode", "(I)V", (void *)setMode}, {"nativeSetMode", "(I)V", (void *)setMode}, {"sendDtmf", "(I)V", (void *)sendDtmf}, {"nativeSendDtmf", "(I)V", (void *)sendDtmf}, }; }; } // namespace } // namespace Loading Loading
voip/java/android/net/rtp/AudioGroup.java +77 −33 Original line number Original line 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 * An AudioGroup acts as a router connected to the speaker, the microphone, and * {@link AudioStream}s. Its pipeline has four steps. First, for each * {@link AudioStream}s. Its execution loop consists of four steps. First, for * AudioStream not in {@link RtpStream#MODE_SEND_ONLY}, decodes its incoming * each AudioStream not in {@link RtpStream#MODE_SEND_ONLY}, decodes its * packets and stores in its buffer. Then, if the microphone is enabled, * incoming packets and stores in its buffer. Then, if the microphone is * processes the recorded audio and stores in its buffer. Third, if the speaker * enabled, processes the recorded audio and stores in its buffer. Third, if the * is enabled, mixes and playbacks buffers of all AudioStreams. Finally, for * speaker is enabled, mixes and playbacks buffers of all AudioStreams. Finally, * each AudioStream not in {@link RtpStream#MODE_RECEIVE_ONLY}, mixes all other * for each AudioStream not in {@link RtpStream#MODE_RECEIVE_ONLY}, mixes all * buffers and sends back the encoded packets. An AudioGroup does nothing if * other buffers and sends back the encoded packets. An AudioGroup does nothing * there is no AudioStream in it. * if there is no AudioStream in it. * * * <p>Few things must be noticed before using these classes. The performance is * <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 * 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 * modes other than {@link #MODE_ON_HOLD}. In addition, before adding an * AudioStream into an AudioGroup, one should always put all other AudioGroups * AudioStream into an AudioGroup, one should always put all other AudioGroups * into {@link #MODE_ON_HOLD}. That will make sure the audio driver correctly * 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 * @hide */ */ public class AudioGroup { public class AudioGroup { Loading Loading @@ -78,6 +83,8 @@ public class AudioGroup { */ */ public static final int MODE_ECHO_SUPPRESSION = 3; public static final int MODE_ECHO_SUPPRESSION = 3; private static final int MODE_LAST = 3; private final Map<AudioStream, Integer> mStreams; private final Map<AudioStream, Integer> mStreams; private int mMode = MODE_ON_HOLD; private int mMode = MODE_ON_HOLD; Loading @@ -93,6 +100,15 @@ public class AudioGroup { mStreams = new HashMap<AudioStream, Integer>(); 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. * Returns the current mode. */ */ Loading @@ -108,18 +124,27 @@ public class AudioGroup { * @param mode The mode to change to. * @param mode The mode to change to. * @throws IllegalArgumentException if the mode is invalid. * @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, private native void nativeSetMode(int mode); int remotePort, String codecSpec, int dtmfType); 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)) { if (!mStreams.containsKey(stream)) { try { try { int socket = stream.dup(); int socket = stream.dup(); String codecSpec = String.format("%d %s %s", codec.type, String codecSpec = String.format("%d %s %s", codec.type, codec.rtpmap, codec.fmtp); codec.rtpmap, codec.fmtp); add(stream.getMode(), socket, nativeAdd(stream.getMode(), socket, stream.getRemoteAddress().getHostAddress(), stream.getRemoteAddress().getHostAddress(), stream.getRemotePort(), codecSpec, dtmfType); stream.getRemotePort(), codecSpec, dtmfType); mStreams.put(stream, socket); 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); Integer socket = mStreams.remove(stream); if (socket != null) { 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 * 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. * @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. * Removes every {@link AudioStream} in this group. */ */ public synchronized void clear() { public void clear() { remove(-1); synchronized (this) { mStreams.clear(); nativeRemove(-1); } } } @Override @Override Loading
voip/java/android/net/rtp/AudioStream.java +17 −11 Original line number Original line 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 * 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 * managing native resources. One can always make an AudioStream leave its * AudioGroup by calling {@link #join(AudioGroup)} with {@code null} and put it * 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 * @see AudioGroup * @hide * @hide */ */ Loading Loading @@ -82,6 +86,7 @@ public class AudioStream extends RtpStream { * @see AudioGroup * @see AudioGroup */ */ public void join(AudioGroup group) { public void join(AudioGroup group) { synchronized (this) { if (mGroup == group) { if (mGroup == group) { return; return; } } Loading @@ -94,6 +99,7 @@ public class AudioStream extends RtpStream { mGroup = group; mGroup = group; } } } } } /** /** * Returns the {@link AudioCodec}, or {@code null} if it is not set. * 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 Original line 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 * RtpStream represents the base class of streams which send and receive network * packets with media payloads over Real-time Transport Protocol (RTP). * 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 * @hide */ */ public class RtpStream { public class RtpStream { Loading @@ -43,6 +46,8 @@ public class RtpStream { */ */ public static final int MODE_RECEIVE_ONLY = 2; public static final int MODE_RECEIVE_ONLY = 2; private static final int MODE_LAST = 2; private final InetAddress mLocalAddress; private final InetAddress mLocalAddress; private final int mLocalPort; private final int mLocalPort; Loading Loading @@ -129,7 +134,7 @@ public class RtpStream { if (isBusy()) { if (isBusy()) { throw new IllegalStateException("Busy"); 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"); throw new IllegalArgumentException("Invalid mode"); } } mMode = mode; mMode = mode; Loading
voip/jni/rtp/AmrCodec.cpp +1 −1 Original line number Original line Diff line number Diff line Loading @@ -73,7 +73,7 @@ int AmrCodec::set(int sampleRate, const char *fmtp) } } // Handle mode-set and octet-align. // Handle mode-set and octet-align. char *modes = (char*)strcasestr(fmtp, "mode-set="); const char *modes = strcasestr(fmtp, "mode-set="); if (modes) { if (modes) { mMode = 0; mMode = 0; mModeSet = 0; mModeSet = 0; Loading
voip/jni/rtp/AudioGroup.cpp +6 −12 Original line number Original line Diff line number Diff line Loading @@ -90,6 +90,7 @@ public: void encode(int tick, AudioStream *chain); void encode(int tick, AudioStream *chain); void decode(int tick); void decode(int tick); private: enum { enum { NORMAL = 0, NORMAL = 0, SEND_ONLY = 1, SEND_ONLY = 1, Loading @@ -97,7 +98,6 @@ public: LAST_MODE = 2, LAST_MODE = 2, }; }; private: int mMode; int mMode; int mSocket; int mSocket; sockaddr_storage mRemote; sockaddr_storage mRemote; Loading Loading @@ -463,6 +463,7 @@ public: bool add(AudioStream *stream); bool add(AudioStream *stream); bool remove(int socket); bool remove(int socket); private: enum { enum { ON_HOLD = 0, ON_HOLD = 0, MUTED = 1, MUTED = 1, Loading @@ -471,7 +472,6 @@ public: LAST_MODE = 3, LAST_MODE = 3, }; }; private: AudioStream *mChain; AudioStream *mChain; int mEventQueue; int mEventQueue; volatile int mDtmfEvent; 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) 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); AudioGroup *group = (AudioGroup *)env->GetIntField(thiz, gNative); if (group && !group->setMode(mode)) { if (group && !group->setMode(mode)) { jniThrowException(env, "java/lang/IllegalArgumentException", NULL); jniThrowException(env, "java/lang/IllegalArgumentException", NULL); return; } } env->SetIntField(thiz, gMode, mode); } } void sendDtmf(JNIEnv *env, jobject thiz, jint event) void sendDtmf(JNIEnv *env, jobject thiz, jint event) Loading @@ -969,10 +963,10 @@ void sendDtmf(JNIEnv *env, jobject thiz, jint event) } } JNINativeMethod gMethods[] = { JNINativeMethod gMethods[] = { {"add", "(IILjava/lang/String;ILjava/lang/String;I)V", (void *)add}, {"nativeAdd", "(IILjava/lang/String;ILjava/lang/String;I)V", (void *)add}, {"remove", "(I)V", (void *)remove}, {"nativeRemove", "(I)V", (void *)remove}, {"setMode", "(I)V", (void *)setMode}, {"nativeSetMode", "(I)V", (void *)setMode}, {"sendDtmf", "(I)V", (void *)sendDtmf}, {"nativeSendDtmf", "(I)V", (void *)sendDtmf}, }; }; } // namespace } // namespace Loading