Merge "RTP: fix few leaks when fail to add streams into a group." into gingerbread

This commit is contained in:
Chia-chi Yeh
2010-08-19 03:36:36 -07:00
committed by Android (Google) Code Review
2 changed files with 21 additions and 17 deletions

View File

@@ -49,27 +49,28 @@ public class AudioGroup {
synchronized void add(AudioStream stream, AudioCodec codec, int codecType, int dtmfType) { synchronized void add(AudioStream stream, AudioCodec codec, int codecType, int dtmfType) {
if (!mStreams.containsKey(stream)) { if (!mStreams.containsKey(stream)) {
try { try {
int id = add(stream.getMode(), stream.dup(), int socket = stream.dup();
add(stream.getMode(), socket,
stream.getRemoteAddress().getHostAddress(), stream.getRemotePort(), stream.getRemoteAddress().getHostAddress(), stream.getRemotePort(),
codec.name, codec.sampleRate, codec.sampleCount, codecType, dtmfType); codec.name, codec.sampleRate, codec.sampleCount, codecType, dtmfType);
mStreams.put(stream, id); mStreams.put(stream, socket);
} catch (NullPointerException e) { } catch (NullPointerException e) {
throw new IllegalStateException(e); throw new IllegalStateException(e);
} }
} }
} }
private native int add(int mode, int socket, String remoteAddress, int remotePort, private native void add(int mode, int socket, String remoteAddress, int remotePort,
String codecName, int sampleRate, int sampleCount, int codecType, int dtmfType); String codecName, int sampleRate, int sampleCount, int codecType, int dtmfType);
synchronized void remove(AudioStream stream) { synchronized void remove(AudioStream stream) {
Integer id = mStreams.remove(stream); Integer socket = mStreams.remove(stream);
if (id != null) { if (socket != null) {
remove(id); remove(socket);
} }
} }
private native void remove(int id); private native void remove(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

View File

@@ -367,7 +367,7 @@ void AudioStream::decode(int tick)
MSG_TRUNC | MSG_DONTWAIT); MSG_TRUNC | MSG_DONTWAIT);
// Do we need to check SSRC, sequence, and timestamp? They are not // Do we need to check SSRC, sequence, and timestamp? They are not
// reliable but at least they can be used to identity duplicates? // reliable but at least they can be used to identify duplicates?
if (length < 12 || length > (int)sizeof(buffer) || if (length < 12 || length > (int)sizeof(buffer) ||
(ntohl(*(uint32_t *)buffer) & 0xC07F0000) != mCodecMagic) { (ntohl(*(uint32_t *)buffer) & 0xC07F0000) != mCodecMagic) {
LOGD("stream[%d] malformed packet", mSocket); LOGD("stream[%d] malformed packet", mSocket);
@@ -697,6 +697,10 @@ bool AudioGroup::remove(int socket)
for (AudioStream *stream = mChain; stream->mNext; stream = stream->mNext) { for (AudioStream *stream = mChain; stream->mNext; stream = stream->mNext) {
AudioStream *target = stream->mNext; AudioStream *target = stream->mNext;
if (target->mSocket == socket) { if (target->mSocket == socket) {
if (epoll_ctl(mEventQueue, EPOLL_CTL_DEL, socket, NULL)) {
LOGE("epoll_ctl: %s", strerror(errno));
return false;
}
stream->mNext = target->mNext; stream->mNext = target->mNext;
LOGD("stream[%d] leaves group[%d]", socket, mDeviceSocket); LOGD("stream[%d] leaves group[%d]", socket, mDeviceSocket);
delete target; delete target;
@@ -800,7 +804,7 @@ bool AudioGroup::deviceLoop()
static jfieldID gNative; static jfieldID gNative;
static jfieldID gMode; static jfieldID gMode;
jint add(JNIEnv *env, jobject thiz, jint mode, void add(JNIEnv *env, jobject thiz, jint mode,
jint socket, jstring jRemoteAddress, jint remotePort, jint socket, jstring jRemoteAddress, jint remotePort,
jstring jCodecName, jint sampleRate, jint sampleCount, jstring jCodecName, jint sampleRate, jint sampleCount,
jint codecType, jint dtmfType) jint codecType, jint dtmfType)
@@ -813,7 +817,7 @@ jint add(JNIEnv *env, jobject thiz, jint mode,
sockaddr_storage remote; sockaddr_storage remote;
if (parse(env, jRemoteAddress, remotePort, &remote) < 0) { if (parse(env, jRemoteAddress, remotePort, &remote) < 0) {
// Exception already thrown. // Exception already thrown.
return -1; goto error;
} }
if (sampleRate < 0 || sampleCount < 0 || codecType < 0 || codecType > 127) { if (sampleRate < 0 || sampleCount < 0 || codecType < 0 || codecType > 127) {
jniThrowException(env, "java/lang/IllegalArgumentException", NULL); jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
@@ -821,12 +825,12 @@ jint add(JNIEnv *env, jobject thiz, jint mode,
} }
if (!jCodecName) { if (!jCodecName) {
jniThrowNullPointerException(env, "codecName"); jniThrowNullPointerException(env, "codecName");
return -1; goto error;
} }
codecName = env->GetStringUTFChars(jCodecName, NULL); codecName = env->GetStringUTFChars(jCodecName, NULL);
if (!codecName) { if (!codecName) {
// Exception already thrown. // Exception already thrown.
return -1; goto error;
} }
// Create audio stream. // Create audio stream.
@@ -835,8 +839,10 @@ jint add(JNIEnv *env, jobject thiz, jint mode,
codecType, dtmfType)) { codecType, dtmfType)) {
jniThrowException(env, "java/lang/IllegalStateException", jniThrowException(env, "java/lang/IllegalStateException",
"cannot initialize audio stream"); "cannot initialize audio stream");
env->ReleaseStringUTFChars(jCodecName, codecName);
goto error; goto error;
} }
env->ReleaseStringUTFChars(jCodecName, codecName);
socket = -1; socket = -1;
// Create audio group. // Create audio group.
@@ -860,16 +866,13 @@ jint add(JNIEnv *env, jobject thiz, jint mode,
// Succeed. // Succeed.
env->SetIntField(thiz, gNative, (int)group); env->SetIntField(thiz, gNative, (int)group);
env->ReleaseStringUTFChars(jCodecName, codecName); return;
return socket;
error: error:
delete group; delete group;
delete stream; delete stream;
close(socket); close(socket);
env->SetIntField(thiz, gNative, NULL); env->SetIntField(thiz, gNative, NULL);
env->ReleaseStringUTFChars(jCodecName, codecName);
return -1;
} }
void remove(JNIEnv *env, jobject thiz, jint socket) void remove(JNIEnv *env, jobject thiz, jint socket)
@@ -902,7 +905,7 @@ void sendDtmf(JNIEnv *env, jobject thiz, jint event)
} }
JNINativeMethod gMethods[] = { JNINativeMethod gMethods[] = {
{"add", "(IILjava/lang/String;ILjava/lang/String;IIII)I", (void *)add}, {"add", "(IILjava/lang/String;ILjava/lang/String;IIII)V", (void *)add},
{"remove", "(I)V", (void *)remove}, {"remove", "(I)V", (void *)remove},
{"setMode", "(I)V", (void *)setMode}, {"setMode", "(I)V", (void *)setMode},
{"sendDtmf", "(I)V", (void *)sendDtmf}, {"sendDtmf", "(I)V", (void *)sendDtmf},