am 4c5d28ce: RTP: move into frameworks.
Merge commit '4c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8' into gingerbread-plus-aosp * commit '4c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8': RTP: move into frameworks.
This commit is contained in:
44
voip/jni/rtp/Android.mk
Normal file
44
voip/jni/rtp/Android.mk
Normal file
@@ -0,0 +1,44 @@
|
||||
#
|
||||
# Copyright (C) 2010 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := librtp_jni
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
AudioCodec.cpp \
|
||||
AudioGroup.cpp \
|
||||
RtpStream.cpp \
|
||||
util.cpp \
|
||||
rtp_jni.cpp
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libnativehelper \
|
||||
libcutils \
|
||||
libutils \
|
||||
libmedia
|
||||
|
||||
LOCAL_STATIC_LIBRARIES :=
|
||||
|
||||
LOCAL_C_INCLUDES += \
|
||||
$(JNI_H_INCLUDE)
|
||||
|
||||
LOCAL_CFLAGS += -fvisibility=hidden
|
||||
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
161
voip/jni/rtp/AudioCodec.cpp
Normal file
161
voip/jni/rtp/AudioCodec.cpp
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyrightm (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "AudioCodec.h"
|
||||
|
||||
namespace {
|
||||
|
||||
int8_t gExponents[128] = {
|
||||
0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class UlawCodec : public AudioCodec
|
||||
{
|
||||
public:
|
||||
bool set(int sampleRate, int sampleCount) {
|
||||
mSampleCount = sampleCount;
|
||||
return sampleCount > 0;
|
||||
}
|
||||
int encode(void *payload, int16_t *samples);
|
||||
int decode(int16_t *samples, void *payload, int length);
|
||||
private:
|
||||
int mSampleCount;
|
||||
};
|
||||
|
||||
int UlawCodec::encode(void *payload, int16_t *samples)
|
||||
{
|
||||
int8_t *ulaws = (int8_t *)payload;
|
||||
for (int i = 0; i < mSampleCount; ++i) {
|
||||
int sample = samples[i];
|
||||
int sign = (sample >> 8) & 0x80;
|
||||
if (sample < 0) {
|
||||
sample = -sample;
|
||||
}
|
||||
sample += 132;
|
||||
if (sample > 32767) {
|
||||
sample = 32767;
|
||||
}
|
||||
int exponent = gExponents[sample >> 8];
|
||||
int mantissa = (sample >> (exponent + 3)) & 0x0F;
|
||||
ulaws[i] = ~(sign | (exponent << 4) | mantissa);
|
||||
}
|
||||
return mSampleCount;
|
||||
}
|
||||
|
||||
int UlawCodec::decode(int16_t *samples, void *payload, int length)
|
||||
{
|
||||
int8_t *ulaws = (int8_t *)payload;
|
||||
for (int i = 0; i < length; ++i) {
|
||||
int ulaw = ~ulaws[i];
|
||||
int exponent = (ulaw >> 4) & 0x07;
|
||||
int mantissa = ulaw & 0x0F;
|
||||
int sample = (((mantissa << 3) + 132) << exponent) - 132;
|
||||
samples[i] = (ulaw < 0 ? -sample : sample);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
AudioCodec *newUlawCodec()
|
||||
{
|
||||
return new UlawCodec;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class AlawCodec : public AudioCodec
|
||||
{
|
||||
public:
|
||||
bool set(int sampleRate, int sampleCount) {
|
||||
mSampleCount = sampleCount;
|
||||
return sampleCount > 0;
|
||||
}
|
||||
int encode(void *payload, int16_t *samples);
|
||||
int decode(int16_t *samples, void *payload, int length);
|
||||
private:
|
||||
int mSampleCount;
|
||||
};
|
||||
|
||||
int AlawCodec::encode(void *payload, int16_t *samples)
|
||||
{
|
||||
int8_t *alaws = (int8_t *)payload;
|
||||
for (int i = 0; i < mSampleCount; ++i) {
|
||||
int sample = samples[i];
|
||||
int sign = (sample >> 8) & 0x80;
|
||||
if (sample < 0) {
|
||||
sample = -sample;
|
||||
}
|
||||
if (sample > 32767) {
|
||||
sample = 32767;
|
||||
}
|
||||
int exponent = gExponents[sample >> 8];
|
||||
int mantissa = (sample >> (exponent == 0 ? 4 : exponent + 3)) & 0x0F;
|
||||
alaws[i] = (sign | (exponent << 4) | mantissa) ^ 0xD5;
|
||||
}
|
||||
return mSampleCount;
|
||||
}
|
||||
|
||||
int AlawCodec::decode(int16_t *samples, void *payload, int length)
|
||||
{
|
||||
int8_t *alaws = (int8_t *)payload;
|
||||
for (int i = 0; i < length; ++i) {
|
||||
int alaw = alaws[i] ^ 0x55;
|
||||
int exponent = (alaw >> 4) & 0x07;
|
||||
int mantissa = alaw & 0x0F;
|
||||
int sample = (exponent == 0 ? (mantissa << 4) + 8 :
|
||||
((mantissa << 3) + 132) << exponent);
|
||||
samples[i] = (alaw < 0 ? sample : -sample);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
AudioCodec *newAlawCodec()
|
||||
{
|
||||
return new AlawCodec;
|
||||
}
|
||||
|
||||
struct AudioCodecType {
|
||||
const char *name;
|
||||
AudioCodec *(*create)();
|
||||
} gAudioCodecTypes[] = {
|
||||
{"PCMA", newAlawCodec},
|
||||
{"PCMU", newUlawCodec},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
AudioCodec *newAudioCodec(const char *codecName)
|
||||
{
|
||||
AudioCodecType *type = gAudioCodecTypes;
|
||||
while (type->name != NULL) {
|
||||
if (strcmp(codecName, type->name) == 0) {
|
||||
return type->create();
|
||||
}
|
||||
++type;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
36
voip/jni/rtp/AudioCodec.h
Normal file
36
voip/jni/rtp/AudioCodec.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyrightm (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef __AUDIO_CODEC_H__
|
||||
#define __AUDIO_CODEC_H__
|
||||
|
||||
class AudioCodec
|
||||
{
|
||||
public:
|
||||
virtual ~AudioCodec() {}
|
||||
// Returns true if initialization succeeds.
|
||||
virtual bool set(int sampleRate, int sampleCount) = 0;
|
||||
// Returns the length of payload in bytes.
|
||||
virtual int encode(void *payload, int16_t *samples) = 0;
|
||||
// Returns the number of decoded samples.
|
||||
virtual int decode(int16_t *samples, void *payload, int length) = 0;
|
||||
};
|
||||
|
||||
AudioCodec *newAudioCodec(const char *codecName);
|
||||
|
||||
#endif
|
||||
1004
voip/jni/rtp/AudioGroup.cpp
Normal file
1004
voip/jni/rtp/AudioGroup.cpp
Normal file
File diff suppressed because it is too large
Load Diff
126
voip/jni/rtp/RtpStream.cpp
Normal file
126
voip/jni/rtp/RtpStream.cpp
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#define LOG_TAG "RtpStream"
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include "jni.h"
|
||||
#include "JNIHelp.h"
|
||||
|
||||
extern int parse(JNIEnv *env, jstring jAddress, int port, sockaddr_storage *ss);
|
||||
|
||||
namespace {
|
||||
|
||||
jfieldID gNative;
|
||||
|
||||
jint create(JNIEnv *env, jobject thiz, jstring jAddress)
|
||||
{
|
||||
env->SetIntField(thiz, gNative, -1);
|
||||
|
||||
sockaddr_storage ss;
|
||||
if (parse(env, jAddress, 0, &ss) < 0) {
|
||||
// Exception already thrown.
|
||||
return -1;
|
||||
}
|
||||
|
||||
int socket = ::socket(ss.ss_family, SOCK_DGRAM, 0);
|
||||
socklen_t len = sizeof(ss);
|
||||
if (socket == -1 || bind(socket, (sockaddr *)&ss, sizeof(ss)) != 0 ||
|
||||
getsockname(socket, (sockaddr *)&ss, &len) != 0) {
|
||||
jniThrowException(env, "java/net/SocketException", strerror(errno));
|
||||
::close(socket);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint16_t *p = (ss.ss_family == AF_INET) ?
|
||||
&((sockaddr_in *)&ss)->sin_port : &((sockaddr_in6 *)&ss)->sin6_port;
|
||||
uint16_t port = ntohs(*p);
|
||||
if ((port & 1) == 0) {
|
||||
env->SetIntField(thiz, gNative, socket);
|
||||
return port;
|
||||
}
|
||||
::close(socket);
|
||||
|
||||
socket = ::socket(ss.ss_family, SOCK_DGRAM, 0);
|
||||
if (socket != -1) {
|
||||
uint16_t delta = port << 1;
|
||||
++port;
|
||||
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
do {
|
||||
port += delta;
|
||||
} while (port < 1024);
|
||||
*p = htons(port);
|
||||
|
||||
if (bind(socket, (sockaddr *)&ss, sizeof(ss)) == 0) {
|
||||
env->SetIntField(thiz, gNative, socket);
|
||||
return port;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jniThrowException(env, "java/net/SocketException", strerror(errno));
|
||||
::close(socket);
|
||||
return -1;
|
||||
}
|
||||
|
||||
jint dup(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
int socket1 = env->GetIntField(thiz, gNative);
|
||||
int socket2 = ::dup(socket1);
|
||||
if (socket2 == -1) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException", strerror(errno));
|
||||
}
|
||||
LOGD("dup %d to %d", socket1, socket2);
|
||||
return socket2;
|
||||
}
|
||||
|
||||
void close(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
int socket = env->GetIntField(thiz, gNative);
|
||||
::close(socket);
|
||||
env->SetIntField(thiz, gNative, -1);
|
||||
LOGD("close %d", socket);
|
||||
}
|
||||
|
||||
JNINativeMethod gMethods[] = {
|
||||
{"create", "(Ljava/lang/String;)I", (void *)create},
|
||||
{"dup", "()I", (void *)dup},
|
||||
{"close", "()V", (void *)close},
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
int registerRtpStream(JNIEnv *env)
|
||||
{
|
||||
jclass clazz;
|
||||
if ((clazz = env->FindClass("android/net/rtp/RtpStream")) == NULL ||
|
||||
(gNative = env->GetFieldID(clazz, "mNative", "I")) == NULL ||
|
||||
env->RegisterNatives(clazz, gMethods, NELEM(gMethods)) < 0) {
|
||||
LOGE("JNI registration failed");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
32
voip/jni/rtp/rtp_jni.cpp
Normal file
32
voip/jni/rtp/rtp_jni.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "jni.h"
|
||||
|
||||
extern int registerRtpStream(JNIEnv *env);
|
||||
extern int registerAudioGroup(JNIEnv *env);
|
||||
|
||||
__attribute__((visibility("default"))) jint JNI_OnLoad(JavaVM *vm, void *unused)
|
||||
{
|
||||
JNIEnv *env = NULL;
|
||||
if (vm->GetEnv((void **)&env, JNI_VERSION_1_4) != JNI_OK ||
|
||||
registerRtpStream(env) < 0 || registerAudioGroup(env) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return JNI_VERSION_1_4;
|
||||
}
|
||||
61
voip/jni/rtp/util.cpp
Normal file
61
voip/jni/rtp/util.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "jni.h"
|
||||
#include "JNIHelp.h"
|
||||
|
||||
int parse(JNIEnv *env, jstring jAddress, int port, sockaddr_storage *ss)
|
||||
{
|
||||
if (!jAddress) {
|
||||
jniThrowNullPointerException(env, "address");
|
||||
return -1;
|
||||
}
|
||||
if (port < 0 || port > 65535) {
|
||||
jniThrowException(env, "java/lang/IllegalArgumentException", "port");
|
||||
return -1;
|
||||
}
|
||||
const char *address = env->GetStringUTFChars(jAddress, NULL);
|
||||
if (!address) {
|
||||
// Exception already thrown.
|
||||
return -1;
|
||||
}
|
||||
memset(ss, 0, sizeof(*ss));
|
||||
|
||||
sockaddr_in *sin = (sockaddr_in *)ss;
|
||||
if (inet_pton(AF_INET, address, &(sin->sin_addr)) > 0) {
|
||||
sin->sin_family = AF_INET;
|
||||
sin->sin_port = htons(port);
|
||||
env->ReleaseStringUTFChars(jAddress, address);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sockaddr_in6 *sin6 = (sockaddr_in6 *)ss;
|
||||
if (inet_pton(AF_INET6, address, &(sin6->sin6_addr)) > 0) {
|
||||
sin6->sin6_family = AF_INET6;
|
||||
sin6->sin6_port = htons(port);
|
||||
env->ReleaseStringUTFChars(jAddress, address);
|
||||
return 0;
|
||||
}
|
||||
|
||||
env->ReleaseStringUTFChars(jAddress, address);
|
||||
jniThrowException(env, "java/lang/IllegalArgumentException", "address");
|
||||
return -1;
|
||||
}
|
||||
Reference in New Issue
Block a user