Merge "RTP: refactor a little bit and fix few minor bugs."

This commit is contained in:
Chia-chi Yeh
2012-03-30 13:34:26 -07:00
committed by Android (Google) Code Review
5 changed files with 54 additions and 55 deletions

View File

@@ -142,34 +142,34 @@ public class AudioGroup {
private native void nativeSetMode(int mode);
// Package-private method used by AudioStream.join().
synchronized void add(AudioStream stream, AudioCodec codec, int dtmfType) {
synchronized void add(AudioStream stream) {
if (!mStreams.containsKey(stream)) {
try {
int socket = stream.dup();
AudioCodec codec = stream.getCodec();
String codecSpec = String.format("%d %s %s", codec.type,
codec.rtpmap, codec.fmtp);
nativeAdd(stream.getMode(), socket,
int id = nativeAdd(stream.getMode(), stream.getSocket(),
stream.getRemoteAddress().getHostAddress(),
stream.getRemotePort(), codecSpec, dtmfType);
mStreams.put(stream, socket);
stream.getRemotePort(), codecSpec, stream.getDtmfType());
mStreams.put(stream, id);
} catch (NullPointerException e) {
throw new IllegalStateException(e);
}
}
}
private native void nativeAdd(int mode, int socket, String remoteAddress,
private native int nativeAdd(int mode, int socket, String remoteAddress,
int remotePort, String codecSpec, int dtmfType);
// Package-private method used by AudioStream.join().
synchronized void remove(AudioStream stream) {
Integer socket = mStreams.remove(stream);
if (socket != null) {
nativeRemove(socket);
Integer id = mStreams.remove(stream);
if (id != null) {
nativeRemove(id);
}
}
private native void nativeRemove(int socket);
private native void nativeRemove(int id);
/**
* Sends a DTMF digit to every {@link AudioStream} in this group. Currently
@@ -192,15 +192,14 @@ public class AudioGroup {
* Removes every {@link AudioStream} in this group.
*/
public void clear() {
synchronized (this) {
mStreams.clear();
nativeRemove(-1);
for (AudioStream stream : getStreams()) {
stream.join(null);
}
}
@Override
protected void finalize() throws Throwable {
clear();
nativeRemove(0);
super.finalize();
}
}

View File

@@ -94,7 +94,7 @@ public class AudioStream extends RtpStream {
mGroup = null;
}
if (group != null) {
group.add(this, mCodec, mDtmfType);
group.add(this);
mGroup = group;
}
}

View File

@@ -54,7 +54,7 @@ public class RtpStream {
private int mRemotePort = -1;
private int mMode = MODE_NORMAL;
private int mNative;
private int mSocket = -1;
static {
System.loadLibrary("rtp_jni");
}
@@ -165,7 +165,9 @@ public class RtpStream {
mRemotePort = port;
}
synchronized native int dup();
int getSocket() {
return mSocket;
}
/**
* Releases allocated resources. The stream becomes inoperable after calling
@@ -175,13 +177,15 @@ public class RtpStream {
* @see #isBusy()
*/
public void release() {
if (isBusy()) {
throw new IllegalStateException("Busy");
synchronized (this) {
if (isBusy()) {
throw new IllegalStateException("Busy");
}
close();
}
close();
}
private synchronized native void close();
private native void close();
@Override
protected void finalize() throws Throwable {

View File

@@ -478,7 +478,7 @@ public:
bool setMode(int mode);
bool sendDtmf(int event);
bool add(AudioStream *stream);
bool remove(int socket);
bool remove(AudioStream *stream);
bool platformHasAec() { return mPlatformHasAec; }
private:
@@ -691,20 +691,19 @@ bool AudioGroup::add(AudioStream *stream)
return true;
}
bool AudioGroup::remove(int socket)
bool AudioGroup::remove(AudioStream *stream)
{
mNetworkThread->requestExitAndWait();
for (AudioStream *stream = mChain; stream->mNext; stream = stream->mNext) {
AudioStream *target = stream->mNext;
if (target->mSocket == socket) {
if (epoll_ctl(mEventQueue, EPOLL_CTL_DEL, socket, NULL)) {
for (AudioStream *chain = mChain; chain->mNext; chain = chain->mNext) {
if (chain->mNext == stream) {
if (epoll_ctl(mEventQueue, EPOLL_CTL_DEL, stream->mSocket, NULL)) {
ALOGE("epoll_ctl: %s", strerror(errno));
return false;
}
stream->mNext = target->mNext;
ALOGD("stream[%d] leaves group[%d]", socket, mDeviceSocket);
delete target;
chain->mNext = stream->mNext;
ALOGD("stream[%d] leaves group[%d]", stream->mSocket, mDeviceSocket);
delete stream;
break;
}
}
@@ -931,7 +930,7 @@ exit:
static jfieldID gNative;
static jfieldID gMode;
void add(JNIEnv *env, jobject thiz, jint mode,
int add(JNIEnv *env, jobject thiz, jint mode,
jint socket, jstring jRemoteAddress, jint remotePort,
jstring jCodecSpec, jint dtmfType)
{
@@ -943,16 +942,22 @@ void add(JNIEnv *env, jobject thiz, jint mode,
sockaddr_storage remote;
if (parse(env, jRemoteAddress, remotePort, &remote) < 0) {
// Exception already thrown.
return;
return 0;
}
if (!jCodecSpec) {
jniThrowNullPointerException(env, "codecSpec");
return;
return 0;
}
const char *codecSpec = env->GetStringUTFChars(jCodecSpec, NULL);
if (!codecSpec) {
// Exception already thrown.
return;
return 0;
}
socket = dup(socket);
if (socket == -1) {
jniThrowException(env, "java/lang/IllegalStateException",
"cannot get stream socket");
return 0;
}
// Create audio codec.
@@ -1001,7 +1006,7 @@ void add(JNIEnv *env, jobject thiz, jint mode,
// Succeed.
env->SetIntField(thiz, gNative, (int)group);
return;
return (int)stream;
error:
delete group;
@@ -1009,13 +1014,14 @@ error:
delete codec;
close(socket);
env->SetIntField(thiz, gNative, 0);
return 0;
}
void remove(JNIEnv *env, jobject thiz, jint socket)
void remove(JNIEnv *env, jobject thiz, jint stream)
{
AudioGroup *group = (AudioGroup *)env->GetIntField(thiz, gNative);
if (group) {
if (socket == -1 || !group->remove(socket)) {
if (!stream || !group->remove((AudioStream *)stream)) {
delete group;
env->SetIntField(thiz, gNative, 0);
}
@@ -1039,7 +1045,7 @@ void sendDtmf(JNIEnv *env, jobject thiz, jint event)
}
JNINativeMethod gMethods[] = {
{"nativeAdd", "(IILjava/lang/String;ILjava/lang/String;I)V", (void *)add},
{"nativeAdd", "(IILjava/lang/String;ILjava/lang/String;I)I", (void *)add},
{"nativeRemove", "(I)V", (void *)remove},
{"nativeSetMode", "(I)V", (void *)setMode},
{"nativeSendDtmf", "(I)V", (void *)sendDtmf},

View File

@@ -33,11 +33,11 @@ extern int parse(JNIEnv *env, jstring jAddress, int port, sockaddr_storage *ss);
namespace {
jfieldID gNative;
jfieldID gSocket;
jint create(JNIEnv *env, jobject thiz, jstring jAddress)
{
env->SetIntField(thiz, gNative, -1);
env->SetIntField(thiz, gSocket, -1);
sockaddr_storage ss;
if (parse(env, jAddress, 0, &ss) < 0) {
@@ -58,7 +58,7 @@ jint create(JNIEnv *env, jobject thiz, jstring jAddress)
&((sockaddr_in *)&ss)->sin_port : &((sockaddr_in6 *)&ss)->sin6_port;
uint16_t port = ntohs(*p);
if ((port & 1) == 0) {
env->SetIntField(thiz, gNative, socket);
env->SetIntField(thiz, gSocket, socket);
return port;
}
::close(socket);
@@ -75,7 +75,7 @@ jint create(JNIEnv *env, jobject thiz, jstring jAddress)
*p = htons(port);
if (bind(socket, (sockaddr *)&ss, sizeof(ss)) == 0) {
env->SetIntField(thiz, gNative, socket);
env->SetIntField(thiz, gSocket, socket);
return port;
}
}
@@ -86,25 +86,15 @@ jint create(JNIEnv *env, jobject thiz, jstring jAddress)
return -1;
}
jint dup(JNIEnv *env, jobject thiz)
{
int socket = ::dup(env->GetIntField(thiz, gNative));
if (socket == -1) {
jniThrowException(env, "java/lang/IllegalStateException", strerror(errno));
}
return socket;
}
void close(JNIEnv *env, jobject thiz)
{
int socket = env->GetIntField(thiz, gNative);
int socket = env->GetIntField(thiz, gSocket);
::close(socket);
env->SetIntField(thiz, gNative, -1);
env->SetIntField(thiz, gSocket, -1);
}
JNINativeMethod gMethods[] = {
{"create", "(Ljava/lang/String;)I", (void *)create},
{"dup", "()I", (void *)dup},
{"close", "()V", (void *)close},
};
@@ -114,7 +104,7 @@ int registerRtpStream(JNIEnv *env)
{
jclass clazz;
if ((clazz = env->FindClass("android/net/rtp/RtpStream")) == NULL ||
(gNative = env->GetFieldID(clazz, "mNative", "I")) == NULL ||
(gSocket = env->GetFieldID(clazz, "mSocket", "I")) == NULL ||
env->RegisterNatives(clazz, gMethods, NELEM(gMethods)) < 0) {
ALOGE("JNI registration failed");
return -1;