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:
Dorel Luca 2018-02-19 21:45:10 +02:00
Родитель 7571df7e7c
Коммит 037478c033
12 изменённых файлов: 228 добавлений и 223 удалений

Просмотреть файл

@ -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;
}; };