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