Add Oboe audio device backend for Android (#2707)
This commit is contained in:
parent
119623b633
commit
639e7dc7e6
95
aconfigure
95
aconfigure
|
@ -693,6 +693,8 @@ ac_android_cflags
|
|||
ac_pjmedia_video_has_android
|
||||
ac_pjmedia_video
|
||||
ac_pjmedia_audiodev_objs
|
||||
ac_oboe_ldflags
|
||||
ac_oboe_cflags
|
||||
ac_pa_cflags
|
||||
ac_external_pa
|
||||
ac_pjmedia_snd
|
||||
|
@ -808,6 +810,7 @@ with_external_webrtc_aec3
|
|||
enable_resample
|
||||
enable_sound
|
||||
with_external_pa
|
||||
with_oboe
|
||||
enable_video
|
||||
enable_ext_sound
|
||||
enable_small_filter
|
||||
|
@ -1570,6 +1573,7 @@ Optional Packages:
|
|||
option is set, make sure that PortAudio is
|
||||
accessible to use (hint: use CFLAGS and LDFLAGS env
|
||||
var to set the include/lib paths)
|
||||
--with-oboe Enable Android Oboe audio device backend.
|
||||
--with-sdl=DIR Specify alternate libSDL prefix
|
||||
--with-ffmpeg=DIR Specify alternate FFMPEG prefix
|
||||
--with-openh264=DIR Specify alternate OpenH264 prefix
|
||||
|
@ -6502,15 +6506,100 @@ else
|
|||
ac_pa_cflags="$ac_pa_cflags -DPA_LITTLE_ENDIAN"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Check whether --with-oboe was given.
|
||||
if test "${with_oboe+set}" = set; then :
|
||||
withval=$with_oboe;
|
||||
if test "x$with_oboe" != "xno" -a "x$with_oboe" != "x"; then
|
||||
OBOE_PREFIX=$with_oboe
|
||||
OBOE_CFLAGS="-I$OBOE_PREFIX/prefab/modules/oboe/include"
|
||||
OBOE_LDFLAGS="-L$OBOE_PREFIX/prefab/modules/oboe/libs/android.$TARGET_ABI"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Using Oboe prefix... $with_oboe" >&5
|
||||
$as_echo "Using Oboe prefix... $with_oboe" >&6; }
|
||||
else
|
||||
OBOE_CFLAGS=""
|
||||
OBOE_LDFLAGS=""
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking Oboe usability" >&5
|
||||
$as_echo_n "checking Oboe usability... " >&6; }
|
||||
|
||||
OBOE_LIBS="-loboe -lOpenSLES -llog"
|
||||
|
||||
SAVED_LIBS="$LIBS"
|
||||
SAVED_LDFLAGS="$LDFLAGS"
|
||||
SAVED_CXXFLAGS="$CXXFLAGS"
|
||||
|
||||
LIBS="$OBOE_LIBS $LIBS"
|
||||
LDFLAGS="$OBOE_LDFLAGS $LDFLAGS"
|
||||
CXXFLAGS="$OBOE_CFLAGS $CXXFLAGS"
|
||||
|
||||
ac_ext=cpp
|
||||
ac_cpp='$CXXCPP $CPPFLAGS'
|
||||
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||
ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
|
||||
ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
|
||||
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <oboe/Oboe.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
oboe::AudioStreamBuilder sb; sb.setDeviceId(0);
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_cxx_try_link "$LINENO"; then :
|
||||
ac_oboe_cflags="-DPJMEDIA_AUDIO_DEV_HAS_OBOE=1 $OBOE_CFLAGS"
|
||||
ac_oboe_ldflags="$OBOE_LDFLAGS $OBOE_LIBS"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
|
||||
else
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
ac_ext=c
|
||||
ac_cpp='$CPP $CPPFLAGS'
|
||||
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
|
||||
ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
|
||||
# Put back original CXXFLAGS as app won't needed it.
|
||||
#LIBS="$SAVED_LIBS"
|
||||
#LDFLAGS="$SAVED_LDFLAGS"
|
||||
CXXFLAGS="$SAVED_CFLAGS"
|
||||
|
||||
|
||||
fi
|
||||
|
||||
|
||||
|
||||
if test "$enable_sound" = "no"; then
|
||||
true;
|
||||
else
|
||||
|
||||
case $target in
|
||||
*android*)
|
||||
LIBS="$LIBS -lOpenSLES"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Checking sound device backend... OpenSL ES" >&5
|
||||
$as_echo "Checking sound device backend... OpenSL ES" >&6; }
|
||||
if test "x$ac_oboe_cflags" != "x"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Checking sound device backend... Oboe" >&5
|
||||
$as_echo "Checking sound device backend... Oboe" >&6; }
|
||||
else
|
||||
LIBS="$LIBS -lOpenSLES"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Checking sound device backend... Android" >&5
|
||||
$as_echo "Checking sound device backend... Android" >&6; }
|
||||
fi
|
||||
;;
|
||||
*-apple-darwin_ios*)
|
||||
LIBS="$LIBS -framework CoreAudio -framework CoreFoundation -framework AudioToolbox -framework CFNetwork -framework UIKit -framework AVFoundation"
|
||||
|
|
|
@ -756,14 +756,69 @@ else
|
|||
ac_pa_cflags="$ac_pa_cflags -DPA_LITTLE_ENDIAN"
|
||||
fi
|
||||
|
||||
|
||||
dnl # Enable Android Oboe audio device
|
||||
AC_SUBST(ac_oboe_cflags)
|
||||
AC_SUBST(ac_oboe_ldflags)
|
||||
AC_ARG_WITH(oboe,
|
||||
AS_HELP_STRING([--with-oboe],
|
||||
[Enable Android Oboe audio device backend.]),
|
||||
[
|
||||
if test "x$with_oboe" != "xno" -a "x$with_oboe" != "x"; then
|
||||
OBOE_PREFIX=$with_oboe
|
||||
OBOE_CFLAGS="-I$OBOE_PREFIX/prefab/modules/oboe/include"
|
||||
OBOE_LDFLAGS="-L$OBOE_PREFIX/prefab/modules/oboe/libs/android.$TARGET_ABI"
|
||||
AC_MSG_RESULT([Using Oboe prefix... $with_oboe])
|
||||
else
|
||||
OBOE_CFLAGS=""
|
||||
OBOE_LDFLAGS=""
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([Oboe usability])
|
||||
|
||||
OBOE_LIBS="-loboe -lOpenSLES -llog"
|
||||
|
||||
SAVED_LIBS="$LIBS"
|
||||
SAVED_LDFLAGS="$LDFLAGS"
|
||||
SAVED_CXXFLAGS="$CXXFLAGS"
|
||||
|
||||
LIBS="$OBOE_LIBS $LIBS"
|
||||
LDFLAGS="$OBOE_LDFLAGS $LDFLAGS"
|
||||
CXXFLAGS="$OBOE_CFLAGS $CXXFLAGS"
|
||||
|
||||
AC_LANG_PUSH([C++])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <oboe/Oboe.h>]],
|
||||
[oboe::AudioStreamBuilder sb; sb.setDeviceId(0);]
|
||||
)],
|
||||
[ ac_oboe_cflags="-DPJMEDIA_AUDIO_DEV_HAS_OBOE=1 $OBOE_CFLAGS"
|
||||
ac_oboe_ldflags="$OBOE_LDFLAGS $OBOE_LIBS"
|
||||
AC_MSG_RESULT(yes)
|
||||
],
|
||||
[
|
||||
LIBS="$SAVED_LIBS"
|
||||
LDFLAGS="$SAVED_LDFLAGS"
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
AC_LANG_POP([C++])
|
||||
|
||||
# Put back original CXXFLAGS as app won't needed it.
|
||||
CXXFLAGS="$SAVED_CFLAGS"
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
if test "$enable_sound" = "no"; then
|
||||
true;
|
||||
else
|
||||
AC_SUBST(ac_pjmedia_audiodev_objs)
|
||||
case $target in
|
||||
*android*)
|
||||
LIBS="$LIBS -lOpenSLES"
|
||||
AC_MSG_RESULT([Checking sound device backend... OpenSL ES])
|
||||
if test "x$ac_oboe_cflags" != "x"; then
|
||||
AC_MSG_RESULT([Checking sound device backend... Oboe])
|
||||
else
|
||||
LIBS="$LIBS -lOpenSLES"
|
||||
AC_MSG_RESULT([Checking sound device backend... Android])
|
||||
fi
|
||||
;;
|
||||
*-apple-darwin_ios*)
|
||||
LIBS="$LIBS -framework CoreAudio -framework CoreFoundation -framework AudioToolbox -framework CFNetwork -framework UIKit -framework AVFoundation"
|
||||
|
|
|
@ -216,6 +216,7 @@ endif
|
|||
|
||||
# Android
|
||||
ANDROID_CFLAGS = @ac_android_cflags@
|
||||
OBOE_CFLAGS = @ac_oboe_cflags@
|
||||
|
||||
# PJMEDIA features exclusion
|
||||
PJ_VIDEO_CFLAGS += $(SDL_CFLAGS) $(FFMPEG_CFLAGS) $(V4L2_CFLAGS) $(DSHOW_CFLAGS) $(QT_CFLAGS) \
|
||||
|
|
|
@ -246,6 +246,9 @@ PJ_DECL(int) pj_thread_get_prio(pj_thread_t *thread);
|
|||
* value range, which can be retrieved with #pj_thread_get_prio_min() and
|
||||
* #pj_thread_get_prio_max() functions.
|
||||
*
|
||||
* For Android, this function will only set the priority of the calling thread
|
||||
* (the thread param must be set to NULL or the calling thread handle).
|
||||
*
|
||||
* @param thread Thread handle.
|
||||
* @param prio New priority to be set to the thread.
|
||||
*
|
||||
|
|
|
@ -69,8 +69,10 @@ JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved)
|
|||
|
||||
return JNI_VERSION_1_4;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
struct pj_thread_t
|
||||
{
|
||||
char obj_name[PJ_MAX_OBJ_NAME];
|
||||
|
@ -303,6 +305,95 @@ PJ_DEF(pj_bool_t) pj_thread_is_registered(void)
|
|||
}
|
||||
|
||||
|
||||
/* Thread priority utils for Android (via JNI as NDK does not provide it).
|
||||
* Set priority is probably not enough because it does not change the thread
|
||||
* group in scheduler.
|
||||
* Temporary solution is to call the Java API to set the thread priority.
|
||||
* A cool solution would be to port (if possible) the code from the
|
||||
* android os regarding set_sched groups.
|
||||
*/
|
||||
#if PJ_ANDROID
|
||||
|
||||
#include <jni.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/system_properties.h>
|
||||
|
||||
PJ_DEF(pj_bool_t) pj_jni_attach_jvm(JNIEnv **jni_env)
|
||||
{
|
||||
if ((*pj_jni_jvm)->GetEnv(pj_jni_jvm, (void **)jni_env,
|
||||
JNI_VERSION_1_4) < 0)
|
||||
{
|
||||
if ((*pj_jni_jvm)->AttachCurrentThread(pj_jni_jvm, jni_env, NULL) < 0)
|
||||
{
|
||||
jni_env = NULL;
|
||||
return PJ_FALSE;
|
||||
}
|
||||
return PJ_TRUE;
|
||||
}
|
||||
|
||||
return PJ_FALSE;
|
||||
}
|
||||
|
||||
PJ_DEF(void) pj_jni_dettach_jvm(pj_bool_t attached)
|
||||
{
|
||||
if (attached)
|
||||
(*pj_jni_jvm)->DetachCurrentThread(pj_jni_jvm);
|
||||
}
|
||||
|
||||
|
||||
static pj_status_t set_android_thread_priority(int priority)
|
||||
{
|
||||
jclass process_class;
|
||||
jmethodID set_prio_method;
|
||||
jthrowable exc;
|
||||
pj_status_t result = PJ_SUCCESS;
|
||||
JNIEnv *jni_env = 0;
|
||||
pj_bool_t attached = pj_jni_attach_jvm(&jni_env);
|
||||
|
||||
PJ_ASSERT_RETURN(jni_env, PJ_FALSE);
|
||||
|
||||
/* Get pointer to the java class */
|
||||
process_class = (jclass)(*jni_env)->NewGlobalRef(jni_env,
|
||||
(*jni_env)->FindClass(jni_env, "android/os/Process"));
|
||||
if (process_class == 0) {
|
||||
PJ_LOG(5, (THIS_FILE, "Unable to find class android.os.Process"));
|
||||
result = PJ_EIGNORED;
|
||||
goto on_return;
|
||||
}
|
||||
|
||||
/* Get the id of set thread priority function */
|
||||
set_prio_method = (*jni_env)->GetStaticMethodID(jni_env, process_class,
|
||||
"setThreadPriority",
|
||||
"(I)V");
|
||||
if (set_prio_method == 0) {
|
||||
PJ_LOG(5, (THIS_FILE, "Unable to find setThreadPriority() method"));
|
||||
result = PJ_EIGNORED;
|
||||
goto on_return;
|
||||
}
|
||||
|
||||
/* Set the thread priority */
|
||||
(*jni_env)->CallStaticVoidMethod(jni_env, process_class, set_prio_method,
|
||||
priority);
|
||||
exc = (*jni_env)->ExceptionOccurred(jni_env);
|
||||
if (exc) {
|
||||
(*jni_env)->ExceptionDescribe(jni_env);
|
||||
(*jni_env)->ExceptionClear(jni_env);
|
||||
PJ_LOG(4, (THIS_FILE, "Failure in setting thread priority using "
|
||||
"Java API, fallback to setpriority()"));
|
||||
setpriority(PRIO_PROCESS, 0, priority);
|
||||
} else {
|
||||
PJ_LOG(5, (THIS_FILE, "Setting thread priority to %d successful",
|
||||
priority));
|
||||
}
|
||||
|
||||
on_return:
|
||||
pj_jni_dettach_jvm(attached);
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Get thread priority value for the thread.
|
||||
*/
|
||||
|
@ -331,6 +422,12 @@ PJ_DEF(int) pj_thread_get_prio(pj_thread_t *thread)
|
|||
PJ_DEF(pj_status_t) pj_thread_set_prio(pj_thread_t *thread, int prio)
|
||||
{
|
||||
#if PJ_HAS_THREADS
|
||||
|
||||
# if PJ_ANDROID
|
||||
PJ_ASSERT_RETURN(thread==NULL || thread==pj_thread_this(), PJ_EINVAL);
|
||||
return set_android_thread_priority(prio);
|
||||
# else
|
||||
|
||||
struct sched_param param;
|
||||
int policy;
|
||||
int rc;
|
||||
|
@ -346,6 +443,9 @@ PJ_DEF(pj_status_t) pj_thread_set_prio(pj_thread_t *thread, int prio)
|
|||
return PJ_RETURN_OS_ERROR(rc);
|
||||
|
||||
return PJ_SUCCESS;
|
||||
|
||||
# endif /* PJ_ANDROID */
|
||||
|
||||
#else
|
||||
PJ_UNUSED_ARG(thread);
|
||||
PJ_UNUSED_ARG(prio);
|
||||
|
|
|
@ -92,7 +92,7 @@ export PJMEDIA_AUDIODEV_SRCDIR = ../src/pjmedia-audiodev
|
|||
export PJMEDIA_AUDIODEV_OBJS += audiodev.o audiotest.o errno.o \
|
||||
legacy_dev.o null_dev.o pa_dev.o wmme_dev.o \
|
||||
alsa_dev.o bb10_dev.o bdimad_dev.o \
|
||||
android_jni_dev.o opensl_dev.o
|
||||
android_jni_dev.o opensl_dev.o oboe_dev.o
|
||||
export PJMEDIA_AUDIODEV_CFLAGS += $(_CFLAGS)
|
||||
export PJMEDIA_AUDIODEV_CXXFLAGS += $(_CXXFLAGS)
|
||||
export PJMEDIA_AUDIODEV_LDFLAGS += $(PJMEDIA_LDLIB) \
|
||||
|
|
|
@ -31,6 +31,8 @@ DARWIN_CFLAGS = @ac_darwin_cflags@
|
|||
|
||||
# Android
|
||||
ANDROID_CFLAGS = @ac_android_cflags@
|
||||
OBOE_CFLAGS = @ac_oboe_cflags@
|
||||
OBOE_LDFLAGS = @ac_oboe_ldflags@
|
||||
|
||||
# openh264
|
||||
OPENH264_CFLAGS = @ac_openh264_cflags@
|
||||
|
@ -45,9 +47,9 @@ VPX_LDFLAGS = @ac_vpx_ldflags@
|
|||
export CFLAGS += @ac_no_small_filter@ @ac_no_large_filter@ @ac_no_speex_aec@ \
|
||||
$(SDL_CFLAGS) $(FFMPEG_CFLAGS) $(V4L2_CFLAGS) $(DSHOW_CFLAGS) $(QT_CFLAGS) \
|
||||
$(DARWIN_CFLAGS) $(ANDROID_CFLAGS) \
|
||||
$(OPENH264_CFLAGS) $(VPX_CFLAGS)
|
||||
$(OPENH264_CFLAGS) $(VPX_CFLAGS) $(OBOE_CFLAGS)
|
||||
export LDFLAGS += $(SDL_LDFLAGS) $(FFMPEG_LDFLAGS) $(V4L2_LDFLAGS) $(DSHOW_LDFLAGS) \
|
||||
$(OPENH264_LDFLAGS) $(VPX_LDFLAGS)
|
||||
$(OPENH264_LDFLAGS) $(VPX_LDFLAGS) $(OBOE_LDFLAGS)
|
||||
|
||||
# Define the desired sound device backend
|
||||
# Valid values are:
|
||||
|
|
|
@ -81,6 +81,14 @@ PJ_BEGIN_DECL
|
|||
# define PJMEDIA_AUDIO_DEV_HAS_ANDROID_JNI PJ_ANDROID
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This setting controls whether Android Oboe audio support should be
|
||||
* included.
|
||||
*/
|
||||
#ifndef PJMEDIA_AUDIO_DEV_HAS_OBOE
|
||||
# define PJMEDIA_AUDIO_DEV_HAS_OBOE 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This setting controls whether BlackBerry 10 (BB10) audio support
|
||||
* should be included.
|
||||
|
|
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* Copyright (C) 2021 Teluu Inc. (http://www.teluu.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
package org.pjsip;
|
||||
|
||||
import android.content.Context;
|
||||
import android.media.AudioDeviceInfo;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class PjAudioDevInfo {
|
||||
|
||||
/* API */
|
||||
|
||||
public int id;
|
||||
public String name;
|
||||
public int direction;
|
||||
public int[] supportedClockRates;
|
||||
public int[] supportedChannelCounts;
|
||||
|
||||
public static int GetCount()
|
||||
{
|
||||
return devices.size();
|
||||
}
|
||||
|
||||
public static PjAudioDevInfo GetInfo(int idx)
|
||||
{
|
||||
return devices.valueAt(idx);
|
||||
}
|
||||
|
||||
public static void RefreshDevices(Context context)
|
||||
{
|
||||
devices = new SparseArray<>();
|
||||
|
||||
/* Default device */
|
||||
PjAudioDevInfo pj_adi = new PjAudioDevInfo();
|
||||
pj_adi.id = 0;
|
||||
pj_adi.name = "Default";
|
||||
pj_adi.direction = 3;
|
||||
devices.put(0, pj_adi);
|
||||
|
||||
/* Enumerate devices (for API level 23 or later) */
|
||||
if (android.os.Build.VERSION.SDK_INT < 23)
|
||||
return;
|
||||
|
||||
AudioManager am = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
|
||||
AudioDeviceInfo[] devs = am.getDevices(AudioManager.GET_DEVICES_ALL);
|
||||
Log.i("Oboe", "Enumerating AudioManager devices..");
|
||||
for (AudioDeviceInfo adi: devs) {
|
||||
LogDevInfo(adi);
|
||||
|
||||
pj_adi = new PjAudioDevInfo();
|
||||
pj_adi.id = adi.getId();
|
||||
pj_adi.name = DevTypeStr(adi.getType()) + " - " + adi.getProductName().toString();
|
||||
pj_adi.direction = 0;
|
||||
if (adi.isSource()) pj_adi.direction |= 1;
|
||||
if (adi.isSink()) pj_adi.direction |= 2;
|
||||
pj_adi.supportedChannelCounts = adi.getChannelCounts();
|
||||
pj_adi.supportedClockRates = adi.getSampleRates();
|
||||
devices.put(adi.getId(), pj_adi);
|
||||
}
|
||||
}
|
||||
|
||||
/* Private members */
|
||||
|
||||
private static SparseArray<PjAudioDevInfo> devices;
|
||||
|
||||
private static String DevTypeStr(int type) {
|
||||
if (android.os.Build.VERSION.SDK_INT < 23)
|
||||
return "Unknown";
|
||||
|
||||
/*
|
||||
if (android.os.Build.VERSION.SDK_INT > 30) {
|
||||
if (type == AudioDeviceInfo.TYPE_BLE_HEADSET)
|
||||
return "BLE Headset";
|
||||
if (type == AudioDeviceInfo.TYPE_BLE_SPEAKER)
|
||||
return "BLE Speaker";
|
||||
}
|
||||
*/
|
||||
|
||||
switch (type) {
|
||||
case AudioDeviceInfo.TYPE_BUILTIN_EARPIECE:
|
||||
return "Builtin Earpiece";
|
||||
case AudioDeviceInfo.TYPE_BUILTIN_SPEAKER:
|
||||
return "Builtin Speaker";
|
||||
case AudioDeviceInfo.TYPE_WIRED_HEADSET:
|
||||
return "Wired Headset";
|
||||
case AudioDeviceInfo.TYPE_WIRED_HEADPHONES:
|
||||
return "Wired Headphones";
|
||||
case AudioDeviceInfo.TYPE_LINE_ANALOG:
|
||||
return "Line Analog";
|
||||
case AudioDeviceInfo.TYPE_LINE_DIGITAL:
|
||||
return "Line Digital";
|
||||
case AudioDeviceInfo.TYPE_BLUETOOTH_SCO:
|
||||
return "Bluetooth SCO";
|
||||
case AudioDeviceInfo.TYPE_BLUETOOTH_A2DP:
|
||||
return "Bluetooth A2DP";
|
||||
case AudioDeviceInfo.TYPE_HDMI:
|
||||
return "HDMI";
|
||||
case AudioDeviceInfo.TYPE_HDMI_ARC:
|
||||
return "HDMI ARC";
|
||||
case AudioDeviceInfo.TYPE_USB_DEVICE:
|
||||
return "USB Device";
|
||||
case AudioDeviceInfo.TYPE_USB_ACCESSORY:
|
||||
return "USB Accessory";
|
||||
case AudioDeviceInfo.TYPE_DOCK:
|
||||
return "Dock";
|
||||
case AudioDeviceInfo.TYPE_FM:
|
||||
return "FM";
|
||||
case AudioDeviceInfo.TYPE_BUILTIN_MIC:
|
||||
return "Builtin Mic";
|
||||
case AudioDeviceInfo.TYPE_FM_TUNER:
|
||||
return "FM Tuner";
|
||||
case AudioDeviceInfo.TYPE_TV_TUNER:
|
||||
return "TV Tuner";
|
||||
case AudioDeviceInfo.TYPE_TELEPHONY:
|
||||
return "Telephony";
|
||||
case AudioDeviceInfo.TYPE_AUX_LINE:
|
||||
return "AUX Line";
|
||||
case AudioDeviceInfo.TYPE_IP:
|
||||
return "IP";
|
||||
case AudioDeviceInfo.TYPE_BUS:
|
||||
return "Bus";
|
||||
case AudioDeviceInfo.TYPE_USB_HEADSET:
|
||||
return "USB Headset";
|
||||
default:
|
||||
return "Unknown ("+ type +")";
|
||||
}
|
||||
}
|
||||
|
||||
private static void LogDevInfo(AudioDeviceInfo adi) {
|
||||
if (Build.VERSION.SDK_INT < 23)
|
||||
return;
|
||||
|
||||
StringBuilder info = new StringBuilder();
|
||||
info.append("id=").append(adi.getId());
|
||||
info.append(",");
|
||||
if (adi.isSource()) info.append(" in");
|
||||
if (adi.isSink()) info.append(" out");
|
||||
info.append(", ").append(DevTypeStr(adi.getType()));
|
||||
if (adi.getChannelCounts().length > 0) {
|
||||
info.append(", channels=").append(Arrays.toString(adi.getChannelCounts()));
|
||||
}
|
||||
if (adi.getSampleRates().length > 0) {
|
||||
info.append(", clock rates=").append(Arrays.toString(adi.getSampleRates()));
|
||||
}
|
||||
Log.i("Oboe", info.toString());
|
||||
}
|
||||
}
|
||||
|
|
@ -141,81 +141,12 @@ static pjmedia_aud_stream_op android_strm_op =
|
|||
&strm_destroy
|
||||
};
|
||||
|
||||
extern JavaVM *pj_jni_jvm;
|
||||
|
||||
static pj_bool_t attach_jvm(JNIEnv **jni_env)
|
||||
{
|
||||
if ((*pj_jni_jvm)->GetEnv(pj_jni_jvm, (void **)jni_env,
|
||||
JNI_VERSION_1_4) < 0)
|
||||
{
|
||||
if ((*pj_jni_jvm)->AttachCurrentThread(pj_jni_jvm, jni_env, NULL) < 0)
|
||||
{
|
||||
jni_env = NULL;
|
||||
return PJ_FALSE;
|
||||
}
|
||||
return PJ_TRUE;
|
||||
}
|
||||
|
||||
return PJ_FALSE;
|
||||
}
|
||||
|
||||
#define detach_jvm(attached) \
|
||||
if (attached) \
|
||||
(*pj_jni_jvm)->DetachCurrentThread(pj_jni_jvm);
|
||||
|
||||
/* Thread priority utils */
|
||||
/* TODO : port it to pj_thread functions */
|
||||
#define THREAD_PRIORITY_AUDIO -16
|
||||
#define THREAD_PRIORITY_URGENT_AUDIO -19
|
||||
|
||||
pj_status_t set_android_thread_priority(int priority)
|
||||
{
|
||||
jclass process_class;
|
||||
jmethodID set_prio_method;
|
||||
jthrowable exc;
|
||||
pj_status_t result = PJ_SUCCESS;
|
||||
JNIEnv *jni_env = 0;
|
||||
pj_bool_t attached = attach_jvm(&jni_env);
|
||||
|
||||
PJ_ASSERT_RETURN(jni_env, PJ_FALSE);
|
||||
|
||||
/* Get pointer to the java class */
|
||||
process_class = (jclass)(*jni_env)->NewGlobalRef(jni_env,
|
||||
(*jni_env)->FindClass(jni_env, "android/os/Process"));
|
||||
if (process_class == 0) {
|
||||
PJ_LOG(4, (THIS_FILE, "Unable to find os process class"));
|
||||
result = PJ_EIGNORED;
|
||||
goto on_return;
|
||||
}
|
||||
|
||||
/* Get the id of set thread priority function */
|
||||
set_prio_method = (*jni_env)->GetStaticMethodID(jni_env, process_class,
|
||||
"setThreadPriority",
|
||||
"(I)V");
|
||||
if (set_prio_method == 0) {
|
||||
PJ_LOG(4, (THIS_FILE, "Unable to find setThreadPriority() method"));
|
||||
result = PJ_EIGNORED;
|
||||
goto on_return;
|
||||
}
|
||||
|
||||
/* Set the thread priority */
|
||||
(*jni_env)->CallStaticVoidMethod(jni_env, process_class, set_prio_method,
|
||||
priority);
|
||||
exc = (*jni_env)->ExceptionOccurred(jni_env);
|
||||
if (exc) {
|
||||
(*jni_env)->ExceptionDescribe(jni_env);
|
||||
(*jni_env)->ExceptionClear(jni_env);
|
||||
PJ_LOG(4, (THIS_FILE, "Failure in setting thread priority using "
|
||||
"Java API, fallback to setpriority()"));
|
||||
setpriority(PRIO_PROCESS, 0, priority);
|
||||
} else {
|
||||
PJ_LOG(4, (THIS_FILE, "Setting thread priority successful"));
|
||||
}
|
||||
|
||||
on_return:
|
||||
detach_jvm(attached);
|
||||
return result;
|
||||
}
|
||||
PJ_DECL(pj_bool_t) pj_jni_attach_jvm(JNIEnv **jni_env);
|
||||
PJ_DECL(void) pj_jni_dettach_jvm(pj_bool_t attached);
|
||||
#define attach_jvm(jni_env) pj_jni_attach_jvm(jni_env)
|
||||
#define detach_jvm(attached) pj_jni_dettach_jvm(attached)
|
||||
#define THREAD_PRIORITY_AUDIO -16
|
||||
#define THREAD_PRIORITY_URGENT_AUDIO -19
|
||||
|
||||
|
||||
static int AndroidRecorderCallback(void *userData)
|
||||
|
@ -255,15 +186,8 @@ static int AndroidRecorderCallback(void *userData)
|
|||
goto on_return;
|
||||
}
|
||||
|
||||
/* Start recording
|
||||
* setpriority(PRIO_PROCESS, 0, -19); //ANDROID_PRIORITY_AUDIO
|
||||
* set priority is probably not enough because it does not change the thread
|
||||
* group in scheduler
|
||||
* Temporary solution is to call the java api to set the thread priority.
|
||||
* A cool solution would be to port (if possible) the code from the
|
||||
* android os regarding set_sched groups
|
||||
*/
|
||||
set_android_thread_priority(THREAD_PRIORITY_URGENT_AUDIO);
|
||||
/* Start recording */
|
||||
pj_thread_set_prio(NULL, THREAD_PRIORITY_URGENT_AUDIO);
|
||||
(*jni_env)->CallVoidMethod(jni_env, stream->record, record_method);
|
||||
|
||||
while (!stream->quit_flag) {
|
||||
|
@ -356,7 +280,7 @@ static int AndroidTrackCallback(void *userData)
|
|||
buf = (*jni_env)->GetByteArrayElements(jni_env, outputBuffer, 0);
|
||||
|
||||
/* Start playing */
|
||||
set_android_thread_priority(THREAD_PRIORITY_URGENT_AUDIO);
|
||||
pj_thread_set_prio(NULL, THREAD_PRIORITY_URGENT_AUDIO);
|
||||
(*jni_env)->CallVoidMethod(jni_env, stream->track, play_method);
|
||||
|
||||
while (!stream->quit_flag) {
|
||||
|
|
|
@ -44,6 +44,10 @@ pjmedia_aud_dev_factory* pjmedia_opensl_factory(pj_pool_factory *pf);
|
|||
pjmedia_aud_dev_factory* pjmedia_android_factory(pj_pool_factory *pf);
|
||||
#endif
|
||||
|
||||
#if PJMEDIA_AUDIO_DEV_HAS_OBOE
|
||||
pjmedia_aud_dev_factory* pjmedia_android_oboe_factory(pj_pool_factory *pf);
|
||||
#endif
|
||||
|
||||
#if PJMEDIA_AUDIO_DEV_HAS_BB10
|
||||
pjmedia_aud_dev_factory* pjmedia_bb10_factory(pj_pool_factory *pf);
|
||||
#endif
|
||||
|
@ -103,6 +107,9 @@ PJ_DEF(pj_status_t) pjmedia_aud_subsys_init(pj_pool_factory *pf)
|
|||
aud_subsys->dev_cnt = 0;
|
||||
|
||||
/* Register creation functions */
|
||||
#if PJMEDIA_AUDIO_DEV_HAS_OBOE
|
||||
aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_android_oboe_factory;
|
||||
#endif
|
||||
#if PJMEDIA_AUDIO_DEV_HAS_OPENSL
|
||||
aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_opensl_factory;
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -190,13 +190,18 @@ $(OUT_DIR)/pjsua2_wrap.cpp: ../pjsua2.i ../symbols.i $(SRCS)
|
|||
|
||||
clean distclean realclean:
|
||||
rm -rf $(LIBPJSUA2_SO) $(OUT_DIR)/* \
|
||||
$(MY_PACKAGE_PATH)/*.java $(MY_PACKAGE_PATH)/*.class
|
||||
$(MY_PACKAGE_PATH)/*.java $(MY_PACKAGE_PATH)/*.class \
|
||||
$(MY_PACKAGE_PATH)/../*.java $(MY_PACKAGE_PATH)/../*.class
|
||||
|
||||
java: $(MY_PACKAGE_PATH)/Error.class $(MY_PACKAGE_PATH)/test.class $(MY_PACKAGE_PATH)/sample.class
|
||||
ifneq (,$(findstring PJMEDIA_VIDEO_DEV_HAS_ANDROID=1,$(ANDROID_CFLAGS)))
|
||||
@echo "Copying Android camera helper components..."
|
||||
cp $(PJDIR)/pjmedia/src/pjmedia-videodev/android/PjCamera*.java $(MY_PACKAGE_PATH)/..
|
||||
endif
|
||||
ifneq (,$(findstring PJMEDIA_AUDIO_DEV_HAS_OBOE=1,$(OBOE_CFLAGS)))
|
||||
@echo "Copying Android Oboe audio device helper components..."
|
||||
cp $(PJDIR)/pjmedia/src/pjmedia-audiodev/android/PjAudioDevInfo.java $(MY_PACKAGE_PATH)/..
|
||||
endif
|
||||
|
||||
$(MY_PACKAGE_PATH)/Error.class: $(MY_PACKAGE_PATH)/Error.java
|
||||
$(MY_JAVAC) -d $(OUT_DIR) $(MY_PACKAGE_PATH)/*.java $(MY_APP_JAVA)
|
||||
|
|
|
@ -3,12 +3,11 @@
|
|||
<component name="FacetManager">
|
||||
<facet type="java-gradle" name="Java-Gradle">
|
||||
<configuration>
|
||||
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
|
||||
<option name="BUILDABLE" value="false" />
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<component name="NewModuleRootManager">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
|
||||
|
|
|
@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
|||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
|
||||
|
|
Loading…
Reference in New Issue