Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4c7cc838 authored by Chia-chi Yeh's avatar Chia-chi Yeh Committed by Android (Google) Code Review
Browse files

Merge "RTP: Prepare to unhide the APIs."

parents 1f245100 53aa6ef7
Loading
Loading
Loading
Loading
+77 −33
Original line number Original line Diff line number Diff line
@@ -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
@@ -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 {
@@ -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;


@@ -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.
     */
     */
@@ -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);
@@ -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
@@ -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
+17 −11
Original line number Original line Diff line number Diff line
@@ -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
 */
 */
@@ -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;
            }
            }
@@ -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.
+6 −1
Original line number Original line Diff line number Diff line
@@ -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 {
@@ -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;


@@ -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;
+1 −1
Original line number Original line Diff line number Diff line
@@ -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;
+6 −12
Original line number Original line Diff line number Diff line
@@ -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,
@@ -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;
@@ -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,
@@ -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;
@@ -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)
@@ -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