Bug 1410456 - Keep the old mechanism for the older versions that jni method is not available. r=padenot

MozReview-Commit-ID: IsAOhDkNjHp

--HG--
extra : rebase_source : 375b7db8bc5d0c433aa55f229d8f81c971a6fbde
This commit is contained in:
Alex Chronopoulos 2018-02-26 13:46:13 +02:00
parent 967d8be756
commit 0d15e89258
3 changed files with 146 additions and 9 deletions

View File

@ -0,0 +1,75 @@
#ifndef _CUBEB_OUTPUT_LATENCY_H_
#define _CUBEB_OUTPUT_LATENCY_H_
#include "cubeb_media_library.h"
#include "../cubeb-jni.h"
struct output_latency_function {
media_lib * from_lib;
cubeb_jni * from_jni;
int version;
};
typedef struct output_latency_function output_latency_function;
const int ANDROID_JELLY_BEAN_MR1_4_2 = 17;
output_latency_function *
cubeb_output_latency_load_method(int version)
{
output_latency_function * ol = NULL;
ol = calloc(1, sizeof(output_latency_function));
ol->version = version;
if (ol->version > ANDROID_JELLY_BEAN_MR1_4_2){
ol->from_jni = cubeb_jni_init();
return ol;
}
ol->from_lib = cubeb_load_media_library();
return ol;
}
bool
cubeb_output_latency_method_is_loaded(output_latency_function * ol)
{
assert(ol && (ol->from_jni || ol->from_lib));
if (ol->version > ANDROID_JELLY_BEAN_MR1_4_2){
return !!ol->from_jni;
}
return !!ol->from_lib;
}
void
cubeb_output_latency_unload_method(output_latency_function * ol)
{
if (!ol) {
return;
}
if (ol->version > ANDROID_JELLY_BEAN_MR1_4_2 && ol->from_jni) {
cubeb_jni_destroy(ol->from_jni);
}
if (ol->version <= ANDROID_JELLY_BEAN_MR1_4_2 && ol->from_lib) {
cubeb_close_media_library(ol->from_lib);
}
free(ol);
}
uint32_t
cubeb_get_output_latency(output_latency_function * ol)
{
assert(cubeb_output_latency_method_is_loaded(ol));
if (ol->version > ANDROID_JELLY_BEAN_MR1_4_2){
return cubeb_get_output_latency_from_jni(ol->from_jni);
}
return cubeb_get_output_latency_from_media_library(ol->from_lib);
}
#endif // _CUBEB_OUTPUT_LATENCY_H_

View File

@ -0,0 +1,62 @@
#ifndef _CUBEB_MEDIA_LIBRARY_H_
#define _CUBEB_MEDIA_LIBRARY_H_
struct media_lib {
void * libmedia;
int32_t (* get_output_latency)(uint32_t * latency, int stream_type);
};
typedef struct media_lib media_lib;
media_lib *
cubeb_load_media_library()
{
media_lib ml = {0};
ml.libmedia = dlopen("libmedia.so", RTLD_LAZY);
if (!ml.libmedia) {
return NULL;
}
// Get the latency, in ms, from AudioFlinger. First, try the most recent signature.
// status_t AudioSystem::getOutputLatency(uint32_t* latency, audio_stream_type_t streamType)
ml.get_output_latency =
dlsym(ml.libmedia, "_ZN7android11AudioSystem16getOutputLatencyEPj19audio_stream_type_t");
if (!ml.get_output_latency) {
// In case of failure, try the signature from legacy version.
// status_t AudioSystem::getOutputLatency(uint32_t* latency, int streamType)
ml.get_output_latency =
dlsym(ml.libmedia, "_ZN7android11AudioSystem16getOutputLatencyEPji");
if (!ml.get_output_latency) {
return NULL;
}
}
media_lib * rv = NULL;
rv = calloc(1, sizeof(media_lib));
assert(rv);
*rv = ml;
return rv;
}
void
cubeb_close_media_library(media_lib * ml)
{
dlclose(ml->libmedia);
ml->libmedia = NULL;
ml->get_output_latency = NULL;
free(ml);
}
uint32_t
cubeb_get_output_latency_from_media_library(media_lib * ml)
{
uint32_t latency = 0;
const int audio_stream_type_music = 3;
int32_t r = ml->get_output_latency(&latency, audio_stream_type_music);
if (r) {
return 0;
}
return latency;
}
#endif // _CUBEB_MEDIA_LIBRARY_H_

View File

@ -26,7 +26,7 @@
#include "cubeb_resampler.h"
#include "cubeb-sles.h"
#include "cubeb_array_queue.h"
#include "cubeb-jni.h"
#include "android/cubeb-output-latency.h"
#if defined(__ANDROID__)
#ifdef LOG
@ -80,7 +80,7 @@ struct cubeb {
SLObjectItf engObj;
SLEngineItf eng;
SLObjectItf outmixObj;
cubeb_jni * jni_obj;
output_latency_function * p_output_latency_function;
};
#define NELEMS(A) (sizeof(A) / sizeof A[0])
@ -741,9 +741,9 @@ opensl_init(cubeb ** context, char const * context_name)
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");
ctx->p_output_latency_function = cubeb_output_latency_load_method(android_version);
if (!ctx->p_output_latency_function) {
LOG("Warning: output latency is not available, cubeb_stream_get_position() is not supported");
}
*context = ctx;
@ -777,8 +777,8 @@ opensl_destroy(cubeb * ctx)
if (ctx->engObj)
cubeb_destroy_sles_engine(&ctx->engObj);
dlclose(ctx->lib);
if (ctx->jni_obj)
cubeb_jni_destroy(ctx->jni_obj);
if (ctx->p_output_latency_function)
cubeb_output_latency_unload_method(ctx->p_output_latency_function);
free(ctx);
}
@ -1452,7 +1452,7 @@ opensl_stream_get_position(cubeb_stream * stm, uint64_t * position)
uint32_t compensation_msec = 0;
SLresult res;
if (!stm->context->jni_obj) {
if (!cubeb_output_latency_method_is_loaded(stm->context->p_output_latency_function)) {
return CUBEB_ERROR_NOT_SUPPORTED;
}
@ -1471,7 +1471,7 @@ opensl_stream_get_position(cubeb_stream * stm, uint64_t * position)
}
uint64_t samplerate = stm->user_output_rate;
uint32_t mixer_latency = cubeb_get_output_latency_from_jni(stm->context->jni_obj);
uint32_t mixer_latency = cubeb_get_output_latency(stm->context->p_output_latency_function);
pthread_mutex_lock(&stm->mutex);
int64_t maximum_position = stm->written * (int64_t)stm->user_output_rate / stm->output_configured_rate;