зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 9 changesets (bug 1410456) for Mochitest failure on mobile/android/tests/browser/chrome/test_media_playback.html
Backed out changeset 36f6b40dfa88 (bug 1410456) Backed out changeset 19f3248502d9 (bug 1410456) Backed out changeset 18ef18999175 (bug 1410456) Backed out changeset 0ec75a56b4c7 (bug 1410456) Backed out changeset f7eae1545d5e (bug 1410456) Backed out changeset d59060ecd24c (bug 1410456) Backed out changeset f996b9dce4a6 (bug 1410456) Backed out changeset 1f75636b5bce (bug 1410456) Backed out changeset c170d37b1a04 (bug 1410456)
This commit is contained in:
Родитель
7571df7e7c
Коммит
037478c033
|
@ -25,9 +25,6 @@
|
||||||
#include "prdtoa.h"
|
#include "prdtoa.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#ifdef MOZ_WIDGET_ANDROID
|
|
||||||
#include "GeneratedJNIWrappers.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define PREF_VOLUME_SCALE "media.volume_scale"
|
#define PREF_VOLUME_SCALE "media.volume_scale"
|
||||||
#define PREF_CUBEB_BACKEND "media.cubeb.backend"
|
#define PREF_CUBEB_BACKEND "media.cubeb.backend"
|
||||||
|
@ -122,8 +119,8 @@ cubeb* sCubebContext;
|
||||||
double sVolumeScale = 1.0;
|
double sVolumeScale = 1.0;
|
||||||
uint32_t sCubebPlaybackLatencyInMilliseconds = 100;
|
uint32_t sCubebPlaybackLatencyInMilliseconds = 100;
|
||||||
uint32_t sCubebMSGLatencyInFrames = 512;
|
uint32_t sCubebMSGLatencyInFrames = 512;
|
||||||
bool sCubebPlaybackLatencyPrefSet = false;
|
bool sCubebPlaybackLatencyPrefSet;
|
||||||
bool sCubebMSGLatencyPrefSet = false;
|
bool sCubebMSGLatencyPrefSet;
|
||||||
bool sAudioStreamInitEverSucceeded = false;
|
bool sAudioStreamInitEverSucceeded = false;
|
||||||
#ifdef MOZ_CUBEB_REMOTING
|
#ifdef MOZ_CUBEB_REMOTING
|
||||||
bool sCubebSandbox;
|
bool sCubebSandbox;
|
||||||
|
@ -308,15 +305,11 @@ bool InitPreferredSampleRate()
|
||||||
if (!context) {
|
if (!context) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#ifdef MOZ_WIDGET_ANDROID
|
|
||||||
sPreferredSampleRate = AndroidGetAudioOutputSampleRate();
|
|
||||||
#else
|
|
||||||
if (cubeb_get_preferred_sample_rate(context,
|
if (cubeb_get_preferred_sample_rate(context,
|
||||||
&sPreferredSampleRate) != CUBEB_OK) {
|
&sPreferredSampleRate) != CUBEB_OK) {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
MOZ_ASSERT(sPreferredSampleRate);
|
MOZ_ASSERT(sPreferredSampleRate);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -534,28 +527,14 @@ bool CubebMSGLatencyPrefSet()
|
||||||
return sCubebMSGLatencyPrefSet;
|
return sCubebMSGLatencyPrefSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t GetCubebMSGLatencyInFrames(cubeb_stream_params * params)
|
Maybe<uint32_t> GetCubebMSGLatencyInFrames()
|
||||||
{
|
{
|
||||||
StaticMutexAutoLock lock(sMutex);
|
StaticMutexAutoLock lock(sMutex);
|
||||||
if (sCubebMSGLatencyPrefSet) {
|
if (!sCubebMSGLatencyPrefSet) {
|
||||||
MOZ_ASSERT(sCubebMSGLatencyInFrames > 0);
|
return Maybe<uint32_t>();
|
||||||
return sCubebMSGLatencyInFrames;
|
|
||||||
}
|
}
|
||||||
|
MOZ_ASSERT(sCubebMSGLatencyInFrames > 0);
|
||||||
#ifdef MOZ_WIDGET_ANDROID
|
return Some(sCubebMSGLatencyInFrames);
|
||||||
return AndroidGetAudioOutputFramesPerBuffer();
|
|
||||||
#else
|
|
||||||
cubeb* context = GetCubebContextUnlocked();
|
|
||||||
if (!context) {
|
|
||||||
return sCubebMSGLatencyInFrames; // default 512
|
|
||||||
}
|
|
||||||
uint32_t latency_frames = 0;
|
|
||||||
if (cubeb_get_min_latency(context, params, &latency_frames) != CUBEB_OK) {
|
|
||||||
NS_WARNING("Could not get minimal latency from cubeb.");
|
|
||||||
return sCubebMSGLatencyInFrames; // default 512
|
|
||||||
}
|
|
||||||
return latency_frames;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitLibrary()
|
void InitLibrary()
|
||||||
|
@ -762,20 +741,5 @@ void GetDeviceCollection(nsTArray<RefPtr<AudioDeviceInfo>>& aDeviceInfos,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MOZ_WIDGET_ANDROID
|
|
||||||
uint32_t AndroidGetAudioOutputSampleRate()
|
|
||||||
{
|
|
||||||
int32_t sample_rate = java::GeckoAppShell::GetAudioOutputSampleRate();
|
|
||||||
MOZ_ASSERT(sample_rate > 0);
|
|
||||||
return sample_rate;
|
|
||||||
}
|
|
||||||
uint32_t AndroidGetAudioOutputFramesPerBuffer()
|
|
||||||
{
|
|
||||||
int32_t frames = java::GeckoAppShell::GetAudioOutputFramesPerBuffer();
|
|
||||||
MOZ_ASSERT(frames > 0);
|
|
||||||
return frames;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace CubebUtils
|
} // namespace CubebUtils
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -44,7 +44,7 @@ cubeb* GetCubebContext();
|
||||||
void ReportCubebStreamInitFailure(bool aIsFirstStream);
|
void ReportCubebStreamInitFailure(bool aIsFirstStream);
|
||||||
void ReportCubebBackendUsed();
|
void ReportCubebBackendUsed();
|
||||||
uint32_t GetCubebPlaybackLatencyInMilliseconds();
|
uint32_t GetCubebPlaybackLatencyInMilliseconds();
|
||||||
uint32_t GetCubebMSGLatencyInFrames(cubeb_stream_params * params);
|
Maybe<uint32_t> GetCubebMSGLatencyInFrames();
|
||||||
bool CubebLatencyPrefSet();
|
bool CubebLatencyPrefSet();
|
||||||
cubeb_channel_layout ConvertChannelMapToCubebLayout(uint32_t aChannelMap);
|
cubeb_channel_layout ConvertChannelMapToCubebLayout(uint32_t aChannelMap);
|
||||||
void GetCurrentBackend(nsAString& aBackend);
|
void GetCurrentBackend(nsAString& aBackend);
|
||||||
|
@ -52,11 +52,6 @@ void GetPreferredChannelLayout(nsAString& aLayout);
|
||||||
void GetDeviceCollection(nsTArray<RefPtr<AudioDeviceInfo>>& aDeviceInfos,
|
void GetDeviceCollection(nsTArray<RefPtr<AudioDeviceInfo>>& aDeviceInfos,
|
||||||
Side aSide);
|
Side aSide);
|
||||||
cubeb_channel_layout GetPreferredChannelLayoutOrSMPTE(cubeb* context, uint32_t aChannels);
|
cubeb_channel_layout GetPreferredChannelLayoutOrSMPTE(cubeb* context, uint32_t aChannels);
|
||||||
|
|
||||||
#ifdef MOZ_WIDGET_ANDROID
|
|
||||||
uint32_t AndroidGetAudioOutputSampleRate();
|
|
||||||
uint32_t AndroidGetAudioOutputFramesPerBuffer();
|
|
||||||
#endif
|
|
||||||
} // namespace CubebUtils
|
} // namespace CubebUtils
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
|
|
|
@ -599,6 +599,7 @@ AudioCallbackDriver::Init()
|
||||||
|
|
||||||
cubeb_stream_params output;
|
cubeb_stream_params output;
|
||||||
cubeb_stream_params input;
|
cubeb_stream_params input;
|
||||||
|
uint32_t latency_frames;
|
||||||
bool firstStream = CubebUtils::GetFirstStream();
|
bool firstStream = CubebUtils::GetFirstStream();
|
||||||
|
|
||||||
MOZ_ASSERT(!NS_IsMainThread(),
|
MOZ_ASSERT(!NS_IsMainThread(),
|
||||||
|
@ -628,7 +629,14 @@ AudioCallbackDriver::Init()
|
||||||
output.layout = CubebUtils::GetPreferredChannelLayoutOrSMPTE(cubebContext, mOutputChannels);
|
output.layout = CubebUtils::GetPreferredChannelLayoutOrSMPTE(cubebContext, mOutputChannels);
|
||||||
output.prefs = CUBEB_STREAM_PREF_NONE;
|
output.prefs = CUBEB_STREAM_PREF_NONE;
|
||||||
|
|
||||||
uint32_t latency_frames = CubebUtils::GetCubebMSGLatencyInFrames(&output);
|
Maybe<uint32_t> latencyPref = CubebUtils::GetCubebMSGLatencyInFrames();
|
||||||
|
if (latencyPref) {
|
||||||
|
latency_frames = latencyPref.value();
|
||||||
|
} else {
|
||||||
|
if (cubeb_get_min_latency(cubebContext, &output, &latency_frames) != CUBEB_OK) {
|
||||||
|
NS_WARNING("Could not get minimal latency from cubeb.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Macbook and MacBook air don't have enough CPU to run very low latency
|
// Macbook and MacBook air don't have enough CPU to run very low latency
|
||||||
// MediaStreamGraphs, cap the minimal latency to 512 frames int this case.
|
// MediaStreamGraphs, cap the minimal latency to 512 frames int this case.
|
||||||
|
|
|
@ -5,4 +5,4 @@ Makefile.in build files for the Mozilla build system.
|
||||||
|
|
||||||
The cubeb git repository is: git://github.com/kinetiknz/cubeb.git
|
The cubeb git repository is: git://github.com/kinetiknz/cubeb.git
|
||||||
|
|
||||||
The git commit ID used was 84e9568141447d13a3f9e03fcff29c2ab6befce1 (2018-02-19 17:50:15 +0200)
|
The git commit ID used was 1d53c3a3779cbeb860b16aa38cc7f51e196b9745 (2018-02-13 12:30:46 +1000)
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
#ifndef _CUBEB_JNI_INSTANCES_H_
|
|
||||||
#define _CUBEB_JNI_INSTANCES_H_
|
|
||||||
|
|
||||||
#include "GeneratedJNIWrappers.h"
|
|
||||||
#include "mozilla/jni/Utils.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The methods in this file offer a way to pass in the required
|
|
||||||
* JNI instances in the cubeb library. By default they return NULL.
|
|
||||||
* In this case part of the cubeb API that depends on JNI
|
|
||||||
* will return CUBEB_ERROR_NOT_SUPPORTED. Currently only one
|
|
||||||
* method depends on that:
|
|
||||||
*
|
|
||||||
* cubeb_stream_get_position()
|
|
||||||
*
|
|
||||||
* Users that want to use that cubeb API method must "override"
|
|
||||||
* the methods bellow to return a valid instance of JavaVM
|
|
||||||
* and application's Context object.
|
|
||||||
* */
|
|
||||||
|
|
||||||
JavaVM *
|
|
||||||
cubeb_jni_get_java_vm()
|
|
||||||
{
|
|
||||||
return mozilla::jni::GetVM();
|
|
||||||
}
|
|
||||||
|
|
||||||
jobject
|
|
||||||
cubeb_jni_get_context_instance()
|
|
||||||
{
|
|
||||||
auto context = mozilla::java::GeckoAppShell::GetApplicationContext();
|
|
||||||
return context.Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //_CUBEB_JNI_INSTANCES_H_
|
|
|
@ -1,88 +0,0 @@
|
||||||
#include "jni.h"
|
|
||||||
#include <assert.h>
|
|
||||||
#include "cubeb-jni-instances.h"
|
|
||||||
|
|
||||||
#define AUDIO_STREAM_TYPE_MUSIC 3
|
|
||||||
|
|
||||||
JNIEnv *
|
|
||||||
cubeb_jni_get_env_for_thread(JavaVM * java_vm)
|
|
||||||
{
|
|
||||||
JNIEnv * env = nullptr;
|
|
||||||
if (!java_vm->AttachCurrentThread(&env, nullptr)) {
|
|
||||||
assert(env);
|
|
||||||
return env;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(false && "Failed to get JNIEnv for thread");
|
|
||||||
return nullptr; // unreachable
|
|
||||||
}
|
|
||||||
|
|
||||||
struct cubeb_jni {
|
|
||||||
JavaVM * s_java_vm = nullptr;
|
|
||||||
jobject s_audio_manager_obj = nullptr;
|
|
||||||
jclass s_audio_manager_class = nullptr;
|
|
||||||
jmethodID s_get_output_latency_id = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
cubeb_jni *
|
|
||||||
cubeb_jni_init()
|
|
||||||
{
|
|
||||||
JavaVM * javaVM = cubeb_jni_get_java_vm();
|
|
||||||
jobject ctx_obj = cubeb_jni_get_context_instance();
|
|
||||||
|
|
||||||
if (!javaVM || !ctx_obj) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEnv * jni_env = cubeb_jni_get_env_for_thread(javaVM);
|
|
||||||
assert(jni_env);
|
|
||||||
|
|
||||||
cubeb_jni * cubeb_jni_ptr = new cubeb_jni;
|
|
||||||
assert(cubeb_jni_ptr);
|
|
||||||
|
|
||||||
cubeb_jni_ptr->s_java_vm = javaVM;
|
|
||||||
|
|
||||||
// Find the audio manager object and make it global to call it from another method
|
|
||||||
jclass context_class = jni_env->FindClass("android/content/Context");
|
|
||||||
jfieldID audio_service_field = jni_env->GetStaticFieldID(context_class, "AUDIO_SERVICE", "Ljava/lang/String;");
|
|
||||||
jstring jstr = (jstring)jni_env->GetStaticObjectField(context_class, audio_service_field);
|
|
||||||
jmethodID get_system_service_id = jni_env->GetMethodID(context_class, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
|
|
||||||
jobject audio_manager_obj = jni_env->CallObjectMethod(ctx_obj, get_system_service_id, jstr);
|
|
||||||
cubeb_jni_ptr->s_audio_manager_obj = reinterpret_cast<jobject>(jni_env->NewGlobalRef(audio_manager_obj));
|
|
||||||
|
|
||||||
// Make the audio manager class a global reference in order to preserve method id
|
|
||||||
jclass audio_manager_class = jni_env->FindClass("android/media/AudioManager");
|
|
||||||
cubeb_jni_ptr->s_audio_manager_class = reinterpret_cast<jclass>(jni_env->NewGlobalRef(audio_manager_class));
|
|
||||||
cubeb_jni_ptr->s_get_output_latency_id = jni_env->GetMethodID (audio_manager_class, "getOutputLatency", "(I)I");
|
|
||||||
|
|
||||||
jni_env->DeleteLocalRef(ctx_obj);
|
|
||||||
jni_env->DeleteLocalRef(context_class);
|
|
||||||
jni_env->DeleteLocalRef(jstr);
|
|
||||||
jni_env->DeleteLocalRef(audio_manager_obj);
|
|
||||||
jni_env->DeleteLocalRef(audio_manager_class);
|
|
||||||
|
|
||||||
return cubeb_jni_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
int cubeb_get_output_latency_from_jni(cubeb_jni * cubeb_jni_ptr)
|
|
||||||
{
|
|
||||||
assert(cubeb_jni_ptr);
|
|
||||||
JNIEnv * jni_env = cubeb_jni_get_env_for_thread(cubeb_jni_ptr->s_java_vm);
|
|
||||||
return jni_env->CallIntMethod(cubeb_jni_ptr->s_audio_manager_obj, cubeb_jni_ptr->s_get_output_latency_id, AUDIO_STREAM_TYPE_MUSIC); //param: AudioManager.STREAM_MUSIC
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
void cubeb_jni_destroy(cubeb_jni * cubeb_jni_ptr)
|
|
||||||
{
|
|
||||||
assert(cubeb_jni_ptr);
|
|
||||||
|
|
||||||
JNIEnv * jni_env = cubeb_jni_get_env_for_thread(cubeb_jni_ptr->s_java_vm);
|
|
||||||
assert(jni_env);
|
|
||||||
|
|
||||||
jni_env->DeleteGlobalRef(cubeb_jni_ptr->s_audio_manager_obj);
|
|
||||||
jni_env->DeleteGlobalRef(cubeb_jni_ptr->s_audio_manager_class);
|
|
||||||
|
|
||||||
delete cubeb_jni_ptr;
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
#ifndef _CUBEB_JNI_H_
|
|
||||||
#define _CUBEB_JNI_H_
|
|
||||||
|
|
||||||
typedef struct cubeb_jni cubeb_jni;
|
|
||||||
|
|
||||||
cubeb_jni * cubeb_jni_init();
|
|
||||||
int cubeb_get_output_latency_from_jni(cubeb_jni * cubeb_jni_ptr);
|
|
||||||
void cubeb_jni_destroy(cubeb_jni * cubeb_jni_ptr);
|
|
||||||
|
|
||||||
#endif // _CUBEB_JNI_H_
|
|
|
@ -26,7 +26,6 @@
|
||||||
#include "cubeb_resampler.h"
|
#include "cubeb_resampler.h"
|
||||||
#include "cubeb-sles.h"
|
#include "cubeb-sles.h"
|
||||||
#include "cubeb_array_queue.h"
|
#include "cubeb_array_queue.h"
|
||||||
#include "cubeb-jni.h"
|
|
||||||
|
|
||||||
#if defined(__ANDROID__)
|
#if defined(__ANDROID__)
|
||||||
#ifdef LOG
|
#ifdef LOG
|
||||||
|
@ -62,13 +61,14 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DEFAULT_SAMPLE_RATE 48000
|
#define DEFAULT_SAMPLE_RATE 48000
|
||||||
#define DEFAULT_NUM_OF_FRAMES 480
|
|
||||||
|
|
||||||
static struct cubeb_ops const opensl_ops;
|
static struct cubeb_ops const opensl_ops;
|
||||||
|
|
||||||
struct cubeb {
|
struct cubeb {
|
||||||
struct cubeb_ops const * ops;
|
struct cubeb_ops const * ops;
|
||||||
void * lib;
|
void * lib;
|
||||||
|
void * libmedia;
|
||||||
|
int32_t (* get_output_latency)(uint32_t * latency, int stream_type);
|
||||||
SLInterfaceID SL_IID_BUFFERQUEUE;
|
SLInterfaceID SL_IID_BUFFERQUEUE;
|
||||||
SLInterfaceID SL_IID_PLAY;
|
SLInterfaceID SL_IID_PLAY;
|
||||||
#if defined(__ANDROID__)
|
#if defined(__ANDROID__)
|
||||||
|
@ -80,11 +80,11 @@ struct cubeb {
|
||||||
SLObjectItf engObj;
|
SLObjectItf engObj;
|
||||||
SLEngineItf eng;
|
SLEngineItf eng;
|
||||||
SLObjectItf outmixObj;
|
SLObjectItf outmixObj;
|
||||||
cubeb_jni * jni_obj;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NELEMS(A) (sizeof(A) / sizeof A[0])
|
#define NELEMS(A) (sizeof(A) / sizeof A[0])
|
||||||
#define NBUFS 4
|
#define NBUFS 4
|
||||||
|
#define AUDIO_STREAM_TYPE_MUSIC 3
|
||||||
|
|
||||||
struct cubeb_stream {
|
struct cubeb_stream {
|
||||||
/* Note: Must match cubeb_stream layout in cubeb.c. */
|
/* Note: Must match cubeb_stream layout in cubeb.c. */
|
||||||
|
@ -153,7 +153,7 @@ struct cubeb_stream {
|
||||||
cubeb_state_callback state_callback;
|
cubeb_state_callback state_callback;
|
||||||
|
|
||||||
cubeb_resampler * resampler;
|
cubeb_resampler * resampler;
|
||||||
unsigned int user_output_rate;
|
unsigned int inputrate;
|
||||||
unsigned int output_configured_rate;
|
unsigned int output_configured_rate;
|
||||||
unsigned int latency_frames;
|
unsigned int latency_frames;
|
||||||
int64_t lastPosition;
|
int64_t lastPosition;
|
||||||
|
@ -236,6 +236,7 @@ static void
|
||||||
play_callback(SLPlayItf caller, void * user_ptr, SLuint32 event)
|
play_callback(SLPlayItf caller, void * user_ptr, SLuint32 event)
|
||||||
{
|
{
|
||||||
cubeb_stream * stm = user_ptr;
|
cubeb_stream * stm = user_ptr;
|
||||||
|
int draining;
|
||||||
assert(stm);
|
assert(stm);
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case SL_PLAYEVENT_HEADATMARKER:
|
case SL_PLAYEVENT_HEADATMARKER:
|
||||||
|
@ -667,11 +668,30 @@ opensl_init(cubeb ** context, char const * context_name)
|
||||||
ctx->ops = &opensl_ops;
|
ctx->ops = &opensl_ops;
|
||||||
|
|
||||||
ctx->lib = dlopen("libOpenSLES.so", RTLD_LAZY);
|
ctx->lib = dlopen("libOpenSLES.so", RTLD_LAZY);
|
||||||
if (!ctx->lib) {
|
ctx->libmedia = dlopen("libmedia.so", RTLD_LAZY);
|
||||||
|
if (!ctx->lib || !ctx->libmedia) {
|
||||||
free(ctx);
|
free(ctx);
|
||||||
return CUBEB_ERROR;
|
return CUBEB_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get the latency, in ms, from AudioFlinger */
|
||||||
|
/* status_t AudioSystem::getOutputLatency(uint32_t* latency,
|
||||||
|
* audio_stream_type_t streamType) */
|
||||||
|
/* First, try the most recent signature. */
|
||||||
|
ctx->get_output_latency =
|
||||||
|
dlsym(ctx->libmedia, "_ZN7android11AudioSystem16getOutputLatencyEPj19audio_stream_type_t");
|
||||||
|
if (!ctx->get_output_latency) {
|
||||||
|
/* in case of failure, try the legacy version. */
|
||||||
|
/* status_t AudioSystem::getOutputLatency(uint32_t* latency,
|
||||||
|
* int streamType) */
|
||||||
|
ctx->get_output_latency =
|
||||||
|
dlsym(ctx->libmedia, "_ZN7android11AudioSystem16getOutputLatencyEPji");
|
||||||
|
if (!ctx->get_output_latency) {
|
||||||
|
opensl_destroy(ctx);
|
||||||
|
return CUBEB_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
typedef SLresult (*slCreateEngine_t)(SLObjectItf *,
|
typedef SLresult (*slCreateEngine_t)(SLObjectItf *,
|
||||||
SLuint32,
|
SLuint32,
|
||||||
const SLEngineOption *,
|
const SLEngineOption *,
|
||||||
|
@ -741,11 +761,6 @@ opensl_init(cubeb ** context, char const * context_name)
|
||||||
return CUBEB_ERROR;
|
return CUBEB_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->jni_obj = cubeb_jni_init();
|
|
||||||
if (!ctx->jni_obj) {
|
|
||||||
LOG("Warning: jni is not initialized, cubeb_stream_get_position() is not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
*context = ctx;
|
*context = ctx;
|
||||||
|
|
||||||
LOG("Cubeb init (%p) success", ctx);
|
LOG("Cubeb init (%p) success", ctx);
|
||||||
|
@ -769,6 +784,124 @@ opensl_get_max_channel_count(cubeb * ctx, uint32_t * max_channels)
|
||||||
return CUBEB_OK;
|
return CUBEB_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
opensl_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate)
|
||||||
|
{
|
||||||
|
/* https://android.googlesource.com/platform/ndk.git/+/master/docs/opensles/index.html
|
||||||
|
* We don't want to deal with JNI here (and we don't have Java on b2g anyways),
|
||||||
|
* so we just dlopen the library and get the two symbols we need. */
|
||||||
|
int r;
|
||||||
|
void * libmedia;
|
||||||
|
uint32_t (*get_primary_output_samplingrate)();
|
||||||
|
uint32_t (*get_output_samplingrate)(int * samplingRate, int streamType);
|
||||||
|
|
||||||
|
libmedia = dlopen("libmedia.so", RTLD_LAZY);
|
||||||
|
if (!libmedia) {
|
||||||
|
return CUBEB_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* uint32_t AudioSystem::getPrimaryOutputSamplingRate(void) */
|
||||||
|
get_primary_output_samplingrate =
|
||||||
|
dlsym(libmedia, "_ZN7android11AudioSystem28getPrimaryOutputSamplingRateEv");
|
||||||
|
if (!get_primary_output_samplingrate) {
|
||||||
|
/* fallback to
|
||||||
|
* status_t AudioSystem::getOutputSamplingRate(int* samplingRate, int streamType)
|
||||||
|
* if we cannot find getPrimaryOutputSamplingRate. */
|
||||||
|
get_output_samplingrate =
|
||||||
|
dlsym(libmedia, "_ZN7android11AudioSystem21getOutputSamplingRateEPj19audio_stream_type_t");
|
||||||
|
if (!get_output_samplingrate) {
|
||||||
|
/* Another signature exists, with a int instead of an audio_stream_type_t */
|
||||||
|
get_output_samplingrate =
|
||||||
|
dlsym(libmedia, "_ZN7android11AudioSystem21getOutputSamplingRateEPii");
|
||||||
|
if (!get_output_samplingrate) {
|
||||||
|
dlclose(libmedia);
|
||||||
|
return CUBEB_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_primary_output_samplingrate) {
|
||||||
|
*rate = get_primary_output_samplingrate();
|
||||||
|
} else {
|
||||||
|
/* We don't really know about the type, here, so we just pass music. */
|
||||||
|
r = get_output_samplingrate((int *) rate, AUDIO_STREAM_TYPE_MUSIC);
|
||||||
|
if (r) {
|
||||||
|
dlclose(libmedia);
|
||||||
|
return CUBEB_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dlclose(libmedia);
|
||||||
|
|
||||||
|
/* Depending on which method we called above, we can get a zero back, yet have
|
||||||
|
* a non-error return value, especially if the audio system is not
|
||||||
|
* ready/shutting down (i.e. when we can't get our hand on the AudioFlinger
|
||||||
|
* thread). */
|
||||||
|
if (*rate == 0) {
|
||||||
|
return CUBEB_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CUBEB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
opensl_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * latency_frames)
|
||||||
|
{
|
||||||
|
/* https://android.googlesource.com/platform/ndk.git/+/master/docs/opensles/index.html
|
||||||
|
* We don't want to deal with JNI here (and we don't have Java on b2g anyways),
|
||||||
|
* so we just dlopen the library and get the two symbols we need. */
|
||||||
|
|
||||||
|
int r;
|
||||||
|
void * libmedia;
|
||||||
|
size_t (*get_primary_output_frame_count)(void);
|
||||||
|
int (*get_output_frame_count)(size_t * frameCount, int streamType);
|
||||||
|
uint32_t primary_sampling_rate;
|
||||||
|
size_t primary_buffer_size;
|
||||||
|
|
||||||
|
r = opensl_get_preferred_sample_rate(ctx, &primary_sampling_rate);
|
||||||
|
|
||||||
|
if (r) {
|
||||||
|
return CUBEB_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
libmedia = dlopen("libmedia.so", RTLD_LAZY);
|
||||||
|
if (!libmedia) {
|
||||||
|
return CUBEB_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* JB variant */
|
||||||
|
/* size_t AudioSystem::getPrimaryOutputFrameCount(void) */
|
||||||
|
get_primary_output_frame_count =
|
||||||
|
dlsym(libmedia, "_ZN7android11AudioSystem26getPrimaryOutputFrameCountEv");
|
||||||
|
if (!get_primary_output_frame_count) {
|
||||||
|
/* ICS variant */
|
||||||
|
/* status_t AudioSystem::getOutputFrameCount(int* frameCount, int streamType) */
|
||||||
|
get_output_frame_count =
|
||||||
|
dlsym(libmedia, "_ZN7android11AudioSystem19getOutputFrameCountEPii");
|
||||||
|
if (!get_output_frame_count) {
|
||||||
|
dlclose(libmedia);
|
||||||
|
return CUBEB_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_primary_output_frame_count) {
|
||||||
|
primary_buffer_size = get_primary_output_frame_count();
|
||||||
|
} else {
|
||||||
|
if (get_output_frame_count(&primary_buffer_size, AUDIO_STREAM_TYPE_MUSIC) != 0) {
|
||||||
|
return CUBEB_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* To get a fast track in Android's mixer, we need to be at the native
|
||||||
|
* samplerate, which is device dependant. Some devices might be able to
|
||||||
|
* resample when playing a fast track, but it's pretty rare. */
|
||||||
|
*latency_frames = primary_buffer_size;
|
||||||
|
|
||||||
|
dlclose(libmedia);
|
||||||
|
|
||||||
|
return CUBEB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
opensl_destroy(cubeb * ctx)
|
opensl_destroy(cubeb * ctx)
|
||||||
{
|
{
|
||||||
|
@ -777,8 +910,7 @@ opensl_destroy(cubeb * ctx)
|
||||||
if (ctx->engObj)
|
if (ctx->engObj)
|
||||||
cubeb_destroy_sles_engine(&ctx->engObj);
|
cubeb_destroy_sles_engine(&ctx->engObj);
|
||||||
dlclose(ctx->lib);
|
dlclose(ctx->lib);
|
||||||
if (ctx->jni_obj)
|
dlclose(ctx->libmedia);
|
||||||
cubeb_jni_destroy(ctx->jni_obj);
|
|
||||||
free(ctx);
|
free(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -865,9 +997,13 @@ opensl_configure_capture(cubeb_stream * stm, cubeb_stream_params * params)
|
||||||
// api for input device this is a safe choice.
|
// api for input device this is a safe choice.
|
||||||
stm->input_device_rate = stm->output_configured_rate;
|
stm->input_device_rate = stm->output_configured_rate;
|
||||||
} else {
|
} else {
|
||||||
// The output preferred rate is used for an input only scenario.
|
// The output preferred rate is used for input only scenario. This is
|
||||||
// The default rate expected to be supported from all android devices.
|
// the correct rate to use to get a fast track for input only.
|
||||||
stm->input_device_rate = DEFAULT_SAMPLE_RATE;
|
r = opensl_get_preferred_sample_rate(stm->context, &stm->input_device_rate);
|
||||||
|
if (r != CUBEB_OK) {
|
||||||
|
// If everything else fail use a safe choice for Android.
|
||||||
|
stm->input_device_rate = DEFAULT_SAMPLE_RATE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
lDataFormat.samplesPerSec = stm->input_device_rate * 1000;
|
lDataFormat.samplesPerSec = stm->input_device_rate * 1000;
|
||||||
res = (*stm->context->eng)->CreateAudioRecorder(stm->context->eng,
|
res = (*stm->context->eng)->CreateAudioRecorder(stm->context->eng,
|
||||||
|
@ -978,7 +1114,7 @@ opensl_configure_playback(cubeb_stream * stm, cubeb_stream_params * params) {
|
||||||
assert(stm);
|
assert(stm);
|
||||||
assert(params);
|
assert(params);
|
||||||
|
|
||||||
stm->user_output_rate = params->rate;
|
stm->inputrate = params->rate;
|
||||||
stm->framesize = params->channels * sizeof(int16_t);
|
stm->framesize = params->channels * sizeof(int16_t);
|
||||||
stm->lastPosition = -1;
|
stm->lastPosition = -1;
|
||||||
stm->lastPositionTimeStamp = 0;
|
stm->lastPositionTimeStamp = 0;
|
||||||
|
@ -1015,7 +1151,20 @@ opensl_configure_playback(cubeb_stream * stm, cubeb_stream_params * params) {
|
||||||
#endif
|
#endif
|
||||||
assert(NELEMS(ids) == NELEMS(req));
|
assert(NELEMS(ids) == NELEMS(req));
|
||||||
|
|
||||||
uint32_t preferred_sampling_rate = stm->user_output_rate;
|
unsigned int latency_frames = stm->latency_frames;
|
||||||
|
uint32_t preferred_sampling_rate = stm->inputrate;
|
||||||
|
#if defined(__ANDROID__)
|
||||||
|
if (get_android_version() >= ANDROID_VERSION_MARSHMALLOW) {
|
||||||
|
// Reset preferred samping rate to trigger fallback to native sampling rate.
|
||||||
|
preferred_sampling_rate = 0;
|
||||||
|
if (opensl_get_min_latency(stm->context, *params, &latency_frames) != CUBEB_OK) {
|
||||||
|
// Default to AudioFlinger's advertised fast track latency of 10ms.
|
||||||
|
latency_frames = 440;
|
||||||
|
}
|
||||||
|
stm->latency_frames = latency_frames;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SLresult res = SL_RESULT_CONTENT_UNSUPPORTED;
|
SLresult res = SL_RESULT_CONTENT_UNSUPPORTED;
|
||||||
if (preferred_sampling_rate) {
|
if (preferred_sampling_rate) {
|
||||||
res = (*stm->context->eng)->CreateAudioPlayer(stm->context->eng,
|
res = (*stm->context->eng)->CreateAudioPlayer(stm->context->eng,
|
||||||
|
@ -1028,9 +1177,12 @@ opensl_configure_playback(cubeb_stream * stm, cubeb_stream_params * params) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sample rate not supported? Try again with primary sample rate!
|
// Sample rate not supported? Try again with primary sample rate!
|
||||||
if (res == SL_RESULT_CONTENT_UNSUPPORTED &&
|
if (res == SL_RESULT_CONTENT_UNSUPPORTED) {
|
||||||
preferred_sampling_rate != DEFAULT_SAMPLE_RATE) {
|
if (opensl_get_preferred_sample_rate(stm->context, &preferred_sampling_rate)) {
|
||||||
preferred_sampling_rate = DEFAULT_SAMPLE_RATE;
|
// If fail default is used
|
||||||
|
preferred_sampling_rate = DEFAULT_SAMPLE_RATE;
|
||||||
|
}
|
||||||
|
|
||||||
format.samplesPerSec = preferred_sampling_rate * 1000;
|
format.samplesPerSec = preferred_sampling_rate * 1000;
|
||||||
res = (*stm->context->eng)->CreateAudioPlayer(stm->context->eng,
|
res = (*stm->context->eng)->CreateAudioPlayer(stm->context->eng,
|
||||||
&stm->playerObj,
|
&stm->playerObj,
|
||||||
|
@ -1048,7 +1200,7 @@ opensl_configure_playback(cubeb_stream * stm, cubeb_stream_params * params) {
|
||||||
|
|
||||||
stm->output_configured_rate = preferred_sampling_rate;
|
stm->output_configured_rate = preferred_sampling_rate;
|
||||||
stm->bytespersec = stm->output_configured_rate * stm->framesize;
|
stm->bytespersec = stm->output_configured_rate * stm->framesize;
|
||||||
stm->queuebuf_len = stm->framesize * stm->latency_frames;
|
stm->queuebuf_len = stm->framesize * latency_frames;
|
||||||
|
|
||||||
// Calculate the capacity of input array
|
// Calculate the capacity of input array
|
||||||
stm->queuebuf_capacity = NBUFS;
|
stm->queuebuf_capacity = NBUFS;
|
||||||
|
@ -1185,7 +1337,7 @@ opensl_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_name
|
||||||
stm->data_callback = data_callback;
|
stm->data_callback = data_callback;
|
||||||
stm->state_callback = state_callback;
|
stm->state_callback = state_callback;
|
||||||
stm->user_ptr = user_ptr;
|
stm->user_ptr = user_ptr;
|
||||||
stm->latency_frames = latency_frames ? latency_frames : DEFAULT_NUM_OF_FRAMES;
|
stm->latency_frames = latency_frames;
|
||||||
stm->input_enabled = (input_stream_params) ? 1 : 0;
|
stm->input_enabled = (input_stream_params) ? 1 : 0;
|
||||||
stm->output_enabled = (output_stream_params) ? 1 : 0;
|
stm->output_enabled = (output_stream_params) ? 1 : 0;
|
||||||
stm->shutdown = 1;
|
stm->shutdown = 1;
|
||||||
|
@ -1449,12 +1601,11 @@ static int
|
||||||
opensl_stream_get_position(cubeb_stream * stm, uint64_t * position)
|
opensl_stream_get_position(cubeb_stream * stm, uint64_t * position)
|
||||||
{
|
{
|
||||||
SLmillisecond msec;
|
SLmillisecond msec;
|
||||||
uint32_t compensation_msec = 0;
|
uint64_t samplerate;
|
||||||
SLresult res;
|
SLresult res;
|
||||||
|
int r;
|
||||||
if (!stm->context->jni_obj) {
|
uint32_t mixer_latency;
|
||||||
return CUBEB_ERROR_NOT_SUPPORTED;
|
uint32_t compensation_msec = 0;
|
||||||
}
|
|
||||||
|
|
||||||
res = (*stm->play)->GetPosition(stm->play, &msec);
|
res = (*stm->play)->GetPosition(stm->play, &msec);
|
||||||
if (res != SL_RESULT_SUCCESS)
|
if (res != SL_RESULT_SUCCESS)
|
||||||
|
@ -1470,11 +1621,15 @@ opensl_stream_get_position(cubeb_stream * stm, uint64_t * position)
|
||||||
stm->lastPosition = msec;
|
stm->lastPosition = msec;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t samplerate = stm->user_output_rate;
|
samplerate = stm->inputrate;
|
||||||
uint32_t mixer_latency = cubeb_get_output_latency_from_jni(stm->context->jni_obj);
|
|
||||||
|
r = stm->context->get_output_latency(&mixer_latency, AUDIO_STREAM_TYPE_MUSIC);
|
||||||
|
if (r) {
|
||||||
|
return CUBEB_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
pthread_mutex_lock(&stm->mutex);
|
pthread_mutex_lock(&stm->mutex);
|
||||||
int64_t maximum_position = stm->written * (int64_t)stm->user_output_rate / stm->output_configured_rate;
|
int64_t maximum_position = stm->written * (int64_t)stm->inputrate / stm->output_configured_rate;
|
||||||
pthread_mutex_unlock(&stm->mutex);
|
pthread_mutex_unlock(&stm->mutex);
|
||||||
assert(maximum_position >= 0);
|
assert(maximum_position >= 0);
|
||||||
|
|
||||||
|
@ -1497,6 +1652,24 @@ opensl_stream_get_position(cubeb_stream * stm, uint64_t * position)
|
||||||
return CUBEB_OK;
|
return CUBEB_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
opensl_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
uint32_t mixer_latency; // The latency returned by AudioFlinger is in ms.
|
||||||
|
|
||||||
|
/* audio_stream_type_t is an int, so this is okay. */
|
||||||
|
r = stm->context->get_output_latency(&mixer_latency, AUDIO_STREAM_TYPE_MUSIC);
|
||||||
|
if (r) {
|
||||||
|
return CUBEB_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*latency = stm->latency_frames + // OpenSL latency
|
||||||
|
mixer_latency * stm->inputrate / 1000; // AudioFlinger latency
|
||||||
|
|
||||||
|
return CUBEB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
opensl_stream_set_volume(cubeb_stream * stm, float volume)
|
opensl_stream_set_volume(cubeb_stream * stm, float volume)
|
||||||
{
|
{
|
||||||
|
@ -1532,8 +1705,8 @@ static struct cubeb_ops const opensl_ops = {
|
||||||
.init = opensl_init,
|
.init = opensl_init,
|
||||||
.get_backend_id = opensl_get_backend_id,
|
.get_backend_id = opensl_get_backend_id,
|
||||||
.get_max_channel_count = opensl_get_max_channel_count,
|
.get_max_channel_count = opensl_get_max_channel_count,
|
||||||
.get_min_latency = NULL,
|
.get_min_latency = opensl_get_min_latency,
|
||||||
.get_preferred_sample_rate = NULL,
|
.get_preferred_sample_rate = opensl_get_preferred_sample_rate,
|
||||||
.get_preferred_channel_layout = NULL,
|
.get_preferred_channel_layout = NULL,
|
||||||
.enumerate_devices = NULL,
|
.enumerate_devices = NULL,
|
||||||
.device_collection_destroy = NULL,
|
.device_collection_destroy = NULL,
|
||||||
|
@ -1544,7 +1717,7 @@ static struct cubeb_ops const opensl_ops = {
|
||||||
.stream_stop = opensl_stream_stop,
|
.stream_stop = opensl_stream_stop,
|
||||||
.stream_reset_default_device = NULL,
|
.stream_reset_default_device = NULL,
|
||||||
.stream_get_position = opensl_stream_get_position,
|
.stream_get_position = opensl_stream_get_position,
|
||||||
.stream_get_latency = NULL,
|
.stream_get_latency = opensl_stream_get_latency,
|
||||||
.stream_set_volume = opensl_stream_set_volume,
|
.stream_set_volume = opensl_stream_set_volume,
|
||||||
.stream_set_panning = NULL,
|
.stream_set_panning = NULL,
|
||||||
.stream_get_current_device = NULL,
|
.stream_get_current_device = NULL,
|
||||||
|
|
|
@ -77,7 +77,6 @@ if CONFIG['OS_TARGET'] == 'WINNT':
|
||||||
if CONFIG['OS_TARGET'] == 'Android':
|
if CONFIG['OS_TARGET'] == 'Android':
|
||||||
SOURCES += ['cubeb_opensl.c']
|
SOURCES += ['cubeb_opensl.c']
|
||||||
SOURCES += ['cubeb_resampler.cpp']
|
SOURCES += ['cubeb_resampler.cpp']
|
||||||
SOURCES += ['cubeb-jni.cpp']
|
|
||||||
DEFINES['USE_OPENSL'] = True
|
DEFINES['USE_OPENSL'] = True
|
||||||
SOURCES += [
|
SOURCES += [
|
||||||
'cubeb_audiotrack.c',
|
'cubeb_audiotrack.c',
|
||||||
|
|
|
@ -20,8 +20,6 @@ cp $1/src/cubeb_log.h src
|
||||||
cp $1/src/cubeb_mixer.cpp src
|
cp $1/src/cubeb_mixer.cpp src
|
||||||
cp $1/src/cubeb_mixer.h src
|
cp $1/src/cubeb_mixer.h src
|
||||||
cp $1/src/cubeb_opensl.c src
|
cp $1/src/cubeb_opensl.c src
|
||||||
cp $1/src/cubeb-jni.cpp src
|
|
||||||
cp $1/src/cubeb-jni.h src
|
|
||||||
cp $1/src/cubeb_osx_run_loop.h src
|
cp $1/src/cubeb_osx_run_loop.h src
|
||||||
cp $1/src/cubeb_panner.cpp src
|
cp $1/src/cubeb_panner.cpp src
|
||||||
cp $1/src/cubeb_panner.h src
|
cp $1/src/cubeb_panner.h src
|
||||||
|
|
|
@ -1836,7 +1836,7 @@ public class GeckoAppShell
|
||||||
return sScreenSize;
|
return sScreenSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@WrapForJNI(calledFrom = "any")
|
@WrapForJNI(calledFrom = "gecko")
|
||||||
public static int getAudioOutputFramesPerBuffer() {
|
public static int getAudioOutputFramesPerBuffer() {
|
||||||
if (SysInfo.getVersion() < 17) {
|
if (SysInfo.getVersion() < 17) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1853,7 +1853,7 @@ public class GeckoAppShell
|
||||||
return Integer.parseInt(prop);
|
return Integer.parseInt(prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
@WrapForJNI(calledFrom = "any")
|
@WrapForJNI(calledFrom = "gecko")
|
||||||
public static int getAudioOutputSampleRate() {
|
public static int getAudioOutputSampleRate() {
|
||||||
if (SysInfo.getVersion() < 17) {
|
if (SysInfo.getVersion() < 17) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -814,7 +814,7 @@ public:
|
||||||
static const mozilla::jni::ExceptionMode exceptionMode =
|
static const mozilla::jni::ExceptionMode exceptionMode =
|
||||||
mozilla::jni::ExceptionMode::ABORT;
|
mozilla::jni::ExceptionMode::ABORT;
|
||||||
static const mozilla::jni::CallingThread callingThread =
|
static const mozilla::jni::CallingThread callingThread =
|
||||||
mozilla::jni::CallingThread::ANY;
|
mozilla::jni::CallingThread::GECKO;
|
||||||
static const mozilla::jni::DispatchTarget dispatchTarget =
|
static const mozilla::jni::DispatchTarget dispatchTarget =
|
||||||
mozilla::jni::DispatchTarget::CURRENT;
|
mozilla::jni::DispatchTarget::CURRENT;
|
||||||
};
|
};
|
||||||
|
@ -833,7 +833,7 @@ public:
|
||||||
static const mozilla::jni::ExceptionMode exceptionMode =
|
static const mozilla::jni::ExceptionMode exceptionMode =
|
||||||
mozilla::jni::ExceptionMode::ABORT;
|
mozilla::jni::ExceptionMode::ABORT;
|
||||||
static const mozilla::jni::CallingThread callingThread =
|
static const mozilla::jni::CallingThread callingThread =
|
||||||
mozilla::jni::CallingThread::ANY;
|
mozilla::jni::CallingThread::GECKO;
|
||||||
static const mozilla::jni::DispatchTarget dispatchTarget =
|
static const mozilla::jni::DispatchTarget dispatchTarget =
|
||||||
mozilla::jni::DispatchTarget::CURRENT;
|
mozilla::jni::DispatchTarget::CURRENT;
|
||||||
};
|
};
|
||||||
|
|
Загрузка…
Ссылка в новой задаче