Commit 07e0e720 authored by Ghislain MARY's avatar Ghislain MARY

Improve audio hack for Galaxy S.

parent d636cd5c
......@@ -559,6 +559,8 @@ enum _MSFilterInterfaceId{
MSFilterVideoCaptureInterface,
MSFilterDecoderInterface,
MSFilterVideoEncoderInterface,
MSFilterAudioCaptureInterface,
MSFilterAudioPlaybackInterface,
};
typedef enum _MSFilterInterfaceId MSFilterInterfaceId;
......
......@@ -150,4 +150,9 @@ typedef enum _MSPlayerState MSPlayerState;
#define MS_VIDEO_ENCODER_REQ_VFU \
MS_FILTER_METHOD_NO_ARG(MSFilterVideoEncoderInterface, 1)
/** Interface definitions for audio capture */
/* Start numbering from the end for hacks */
#define MS_AUDIO_CAPTURE_FORCE_SPEAKER_STATE \
MS_FILTER_METHOD(MSFilterAudioCaptureInterface, 255, bool_t)
#endif
......@@ -21,7 +21,6 @@ package org.linphone.mediastream.video.capture.hwconf;
import org.linphone.mediastream.Version;
import android.hardware.Camera;
import android.media.AudioManager;
import android.os.Build;
import android.util.Log;
......@@ -83,32 +82,6 @@ public final class Hacks {
// LG with two cameras
private static final boolean isLGP970() {return Build.DEVICE.startsWith("LG-P970");}
/* private static final boolean log(final String msg) {
Log.d(msg);
return true;
}*/
/* Not working as now
* Calling from Galaxy S to PC is "usable" even with no hack; other side is not even with this one*/
public static void galaxySSwitchToCallStreamUnMuteLowerVolume(AudioManager am) {
// Switch to call audio channel (Galaxy S)
am.setSpeakerphoneOn(false);
sleep(200);
// Lower volume
am.setStreamVolume(AudioManager.STREAM_VOICE_CALL, 1, 0);
// Another way to select call channel
am.setMode(AudioManager.MODE_NORMAL);
sleep(200);
// Mic is muted if not doing this
am.setMicrophoneMute(true);
sleep(200);
am.setMicrophoneMute(false);
sleep(200);
}
public static final void sleep(int time) {
try {
Thread.sleep(time);
......@@ -116,11 +89,7 @@ public final class Hacks {
}
public static boolean needSoftvolume() {
return isGalaxySOrTab() && Version.sdkStrictlyBelow(Version.API14_ICE_CREAM_SANDWICH_40);
}
public static boolean needRoutingAPI() {
return Version.sdkStrictlyBelow(5);
return isGalaxySOrTab() && Version.sdkStrictlyBelow(Version.API09_GINGERBREAD_23);
}
public static boolean needGalaxySAudioHack() {
......@@ -128,8 +97,7 @@ public final class Hacks {
}
public static boolean needPausingCallForSpeakers() {
return false;
//return isGalaxySOrTab() && !isSC02B();
return needGalaxySAudioHack();
}
public static boolean hasCamera() {
......
......@@ -51,6 +51,14 @@ status_t AudioSystem::setParameters(audio_io_handle_t ioHandle, const String8& k
return AudioSystemImpl::get()->mSetParameters.invoke(ioHandle,keyValuePairs);
}
status_t AudioSystem::setPhoneState(audio_mode_t state) {
return AudioSystemImpl::get()->mSetPhoneState.invoke(state);
}
status_t AudioSystem::setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config) {
return AudioSystemImpl::get()->mSetForceUse.invoke(usage, config);
}
audio_io_handle_t AudioSystem::getInput(audio_source_t inputSource,
uint32_t samplingRate,
audio_format_t format,
......@@ -68,10 +76,17 @@ AudioSystemImpl::AudioSystemImpl(Library *lib) :
mGetOutputSamplingRate(lib,"_ZN7android11AudioSystem21getOutputSamplingRateEPii"),
mGetOutputFrameCount(lib, "_ZN7android11AudioSystem19getOutputFrameCountEPii"),
mGetOutputLatency(lib, "_ZN7android11AudioSystem16getOutputLatencyEPji"),
mSetParameters(lib,"_ZN7android11AudioSystem13setParametersEiRKNS_7String8E"){
mSetParameters(lib,"_ZN7android11AudioSystem13setParametersEiRKNS_7String8E"),
mSetPhoneState(lib, "_ZN7android11AudioSystem13setPhoneStateEi"),
mSetForceUse(lib, "_ZN7android11AudioSystem11setForceUseENS0_9force_useENS0_13forced_configE") {
//mGetInput(lib,"_ZN7android11AudioSystem8getInputEijjjNS0_18audio_in_acousticsE"){
// Try some Android 4.1 symbols if not found
// Try some Android 4.0 symbols if not found
if (!mSetForceUse.isFound()) {
mSetForceUse.load(lib, "_ZN7android11AudioSystem11setForceUseE24audio_policy_force_use_t25audio_policy_forced_cfg_t");
}
// Then try some Android 4.1 symbols if still not found
if (!mGetOutputSamplingRate.isFound()) {
mGetOutputSamplingRate.load(lib, "_ZN7android11AudioSystem21getOutputSamplingRateEPi19audio_stream_type_t");
}
......@@ -81,6 +96,9 @@ AudioSystemImpl::AudioSystemImpl(Library *lib) :
if (!mGetOutputLatency.isFound()) {
mGetOutputLatency.load(lib, "_ZN7android11AudioSystem16getOutputLatencyEPj19audio_stream_type_t");
}
if (!mSetPhoneState.isFound()) {
mSetPhoneState.load(lib, "_ZN7android11AudioSystem13setPhoneStateE12audio_mode_t");
}
}
bool AudioSystemImpl::init(Library *lib){
......@@ -95,6 +113,8 @@ bool AudioSystemImpl::init(Library *lib){
if (!impl->mGetOutputFrameCount.isFound()) goto fail;
if (!impl->mGetOutputLatency.isFound()) goto fail;
if (!impl->mSetParameters.isFound()) goto fail;
if (!impl->mSetPhoneState.isFound()) goto fail;
if (!impl->mSetForceUse.isFound()) goto fail;
//if (!impl->mGetInput.isFound()) goto fail;
err = impl->mGetOutputSamplingRate.invoke(&samplingRate, AUDIO_STREAM_VOICE_CALL);
......
......@@ -184,10 +184,10 @@ public:
//
/*
static status_t setDeviceConnectionState(audio_devices_t device, audio_policy_dev_state_t state, const char *device_address);
static audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device, const char *device_address);
static audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device, const char *device_address);*/
static status_t setPhoneState(audio_mode_t state);
static status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config);
static audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage);
/*static audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage);
static audio_io_handle_t getOutput(audio_stream_type_t stream,
uint32_t samplingRate = 0,
audio_format_t format = AUDIO_FORMAT_DEFAULT,
......@@ -252,6 +252,8 @@ public:
Function2<status_t, int *, int> mGetOutputFrameCount;
Function2<status_t, uint32_t *, int> mGetOutputLatency;
Function2<status_t,audio_io_handle_t,const String8 &> mSetParameters;
Function1<status_t, audio_mode_t> mSetPhoneState;
Function2<status_t, audio_policy_force_use_t, audio_policy_forced_cfg_t> mSetForceUse;
//Function6<audio_io_handle_t,audio_source_t,uint32_t,audio_format_t,uint32_t,audio_in_acoustics_t,int> mGetInput;
private:
AudioSystemImpl(Library *lib);
......
......@@ -135,7 +135,7 @@ struct AndroidSndReadData{
mCard=card;
#ifdef NATIVE_USE_HARDWARE_RATE
rate=card->mRecRate;
rec_buf_size=card->mRecFrames;
rec_buf_size=card->mRecFrames * 4;
#endif
}
MSFilter *mFilter;
......@@ -299,7 +299,6 @@ static void android_snd_read_preprocess(MSFilter *obj){
ad->mCard->enableVoipMode();
ad->rec_buf_size*=4;
ad->mFilter=obj;
ad->read_samples=0;
ad->audio_source=AUDIO_SOURCE_VOICE_COMMUNICATION;
......@@ -322,7 +321,12 @@ static void android_snd_read_preprocess(MSFilter *obj){
}
}else break;
}
if (ad->rec != 0) {
ad->started=true;
ad->rec->start();
}
}
static void android_snd_read_postprocess(MSFilter *obj){
......@@ -351,13 +355,12 @@ static void android_snd_read_uninit(MSFilter *obj){
static void android_snd_read_process(MSFilter *obj){
AndroidSndReadData *ad=(AndroidSndReadData*)obj->data;
mblk_t *om;
if (ad->rec==0) return;
if (!ad->started) {
ad->started=true;
ad->rec->start();
ms_mutex_lock(&ad->mutex);
if ((ad->rec == 0) || !ad->started) {
ms_mutex_unlock(&ad->mutex);
return;
}
ms_mutex_lock(&ad->mutex);
while ((om=getq(&ad->q))!=NULL) {
//ms_message("android_snd_read_process: Outputing %i bytes",msgdsize(om));
ms_queue_put(obj->outputs[0],om);
......@@ -388,10 +391,45 @@ static int android_snd_read_set_nchannels(MSFilter *obj, void *param){
return 0;
}
static int android_snd_read_hack_speaker_state(MSFilter *f, void *arg) {
AndroidSndReadData *ad = (AndroidSndReadData *)f->data;
bool speakerOn = *((bool *)arg);
if (!ad->started) {
ms_error("Audio recorder not started, can't hack speaker");
return -1;
}
ms_mutex_lock(&ad->mutex);
ad->started = false;
ms_mutex_unlock(&ad->mutex);
// Stop audio recorder
ms_message("Hacking speaker state: calling android_snd_read_postprocess()");
android_snd_read_postprocess(f);
// Flush eventual sound in the buffer
// No need to lock as reader_cb is stopped
flushq(&ad->q, 0);
AudioSystem::setPhoneState(AUDIO_MODE_IN_CALL);
if (speakerOn)
AudioSystem::setForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION, AUDIO_POLICY_FORCE_SPEAKER);
else
AudioSystem::setForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION, AUDIO_POLICY_FORCE_NONE);
// Re-open audio and set d->started=true
ms_message("Hacking speaker state: calling android_snd_read_preprocess()");
android_snd_read_preprocess(f);
return 0;
}
MSFilterMethod android_snd_read_methods[]={
{MS_FILTER_SET_SAMPLE_RATE, android_snd_read_set_sample_rate},
{MS_FILTER_GET_SAMPLE_RATE, android_snd_read_get_sample_rate},
{MS_FILTER_SET_NCHANNELS, android_snd_read_set_nchannels},
{MS_AUDIO_CAPTURE_FORCE_SPEAKER_STATE, android_snd_read_hack_speaker_state},
{0,NULL}
};
......
......@@ -361,6 +361,37 @@ typedef enum {
} audio_output_flags_t;
/* device categories used for audio_policy->set_force_use() */
typedef enum {
AUDIO_POLICY_FORCE_NONE,
AUDIO_POLICY_FORCE_SPEAKER,
AUDIO_POLICY_FORCE_HEADPHONES,
AUDIO_POLICY_FORCE_BT_SCO,
AUDIO_POLICY_FORCE_BT_A2DP,
AUDIO_POLICY_FORCE_WIRED_ACCESSORY,
AUDIO_POLICY_FORCE_BT_CAR_DOCK,
AUDIO_POLICY_FORCE_BT_DESK_DOCK,
AUDIO_POLICY_FORCE_ANALOG_DOCK,
AUDIO_POLICY_FORCE_DIGITAL_DOCK,
AUDIO_POLICY_FORCE_CFG_CNT,
AUDIO_POLICY_FORCE_CFG_MAX = AUDIO_POLICY_FORCE_CFG_CNT - 1,
AUDIO_POLICY_FORCE_DEFAULT = AUDIO_POLICY_FORCE_NONE,
} audio_policy_forced_cfg_t;
/* usages used for audio_policy->set_force_use() */
typedef enum {
AUDIO_POLICY_FORCE_FOR_COMMUNICATION,
AUDIO_POLICY_FORCE_FOR_MEDIA,
AUDIO_POLICY_FORCE_FOR_RECORD,
AUDIO_POLICY_FORCE_FOR_DOCK,
AUDIO_POLICY_FORCE_USE_CNT,
AUDIO_POLICY_FORCE_USE_MAX = AUDIO_POLICY_FORCE_USE_CNT - 1,
} audio_policy_force_use_t;
/*
static inline bool audio_is_output_device(audio_devices_t device)
{
......
......@@ -31,7 +31,6 @@
#include "ortp/zrtp.h"
#include <cpu-features.h>
static MSFilter *hackLastSoundReadFilter=0; // hack for Galaxy S
static const float sndwrite_flush_threshold=0.020; //ms
static const float sndread_flush_threshold=0.020; //ms
......@@ -237,13 +236,15 @@ static int get_latency(MSFilter *f, void *arg){
}
return 0;
}
static int msandroid_hack_speaker_state(MSFilter *f, void *arg);
MSFilterMethod msandroid_sound_read_methods[]={
{ MS_FILTER_SET_SAMPLE_RATE , set_read_rate },
{ MS_FILTER_GET_SAMPLE_RATE , get_rate },
{ MS_FILTER_SET_NCHANNELS , set_nchannels },
{ MS_FILTER_GET_LATENCY , get_latency},
{ MS_AUDIO_CAPTURE_FORCE_SPEAKER_STATE, msandroid_hack_speaker_state },
{ 0 , NULL }
};
......@@ -512,7 +513,6 @@ MSFilter *msandroid_sound_read_new(MSSndCard *card){
ms_debug("msandroid_sound_read_new");
MSFilter *f=ms_filter_new_from_desc(&msandroid_sound_read_desc);
f->data=new msandroid_sound_read_data();
hackLastSoundReadFilter=f;
return f;
}
......@@ -830,36 +830,50 @@ MSFilter *msandroid_sound_write_new(MSSndCard *card){
MS_FILTER_DESC_EXPORT(msandroid_sound_write_desc)
/******* Hack for Galaxy S ***********/
extern "C" void msandroid_hack_speaker_state(bool speakerOn) {
msandroid_sound_read_data *d=(msandroid_sound_read_data*)hackLastSoundReadFilter->data;
static int msandroid_hack_speaker_state(MSFilter *f, void *arg) {
msandroid_sound_read_data *d=(msandroid_sound_read_data*)f->data;
bool speakerOn = *((bool *)arg);
if (!d->started) {
ms_error("Audio recorder not started, can't hack speaker");
return;
return -1;
}
JNIEnv *jni_env = ms_get_jni_env();
// First, check that required methods are found
jclass linphone_manager_class= (jclass)jni_env->NewGlobalRef(jni_env->FindClass("org/linphone/LinphoneManager"));
if (linphone_manager_class == 0) {
ms_error("Cannot find org/linphone/LinphoneManager\n");
return;
jclass LinphoneManager_class = (jclass)jni_env->NewGlobalRef(jni_env->FindClass("org/linphone/LinphoneManager"));
if (LinphoneManager_class == 0) {
ms_error("Cannot find org/linphone/LinphoneManager");
return -1;
}
jmethodID helperhelper_id=jni_env->GetStaticMethodID(linphone_manager_class,"sRouteAudioToSpeakerHelperHelper", "(Z)V");
if (helperhelper_id == 0) {
ms_error("Cannot find LinphoneManager.sRouteAudioToSpeakerHelperHelper(boolean)");
return;
jclass LinphoneCoreImpl_class = (jclass)jni_env->NewGlobalRef(jni_env->FindClass("org/linphone/core/LinphoneCoreImpl"));
if (LinphoneCoreImpl_class == 0) {
ms_error("Cannot find org/linphone/core/LinphoneCoreImpl");
return -1;
}
jmethodID getLc_id = jni_env->GetStaticMethodID(LinphoneManager_class, "getLc", "()Lorg/linphone/core/LinphoneCore;");
if (getLc_id == 0) {
ms_error("Cannot find LinphoneManager.getLc()");
return -1;
}
jmethodID routeAudioToSpeakerHelper_id = jni_env->GetMethodID(LinphoneCoreImpl_class,"routeAudioToSpeakerHelper", "(Z)V");
if (routeAudioToSpeakerHelper_id == 0) {
ms_error("Cannot find LinphoneCoreImpl.routeAudioToSpeakerHelper()");
return -1;
}
jobject lc = jni_env->CallStaticObjectMethod(LinphoneManager_class, getLc_id);
ms_mutex_lock(&d->mutex);
d->started=false;
d->started = false;
ms_mutex_unlock(&d->mutex);
// Stop audio recorder
ms_message("Hacking speaker state: calling sound_read_postprocess()");
sound_read_postprocess(hackLastSoundReadFilter);
sound_read_postprocess(f);
// Flush eventual sound in the buffer
// No need to lock as reader_cb is stopped
......@@ -867,12 +881,14 @@ extern "C" void msandroid_hack_speaker_state(bool speakerOn) {
// Change speaker state by calling back to java code
// as there seems to be no way to get a reference to AudioManager service.
ms_message("Hacking speaker state: do magic from LinphoneManager.sRouteAudioToSpeakerHelperHelper()");
jni_env->CallStaticVoidMethod(linphone_manager_class,helperhelper_id,speakerOn);
ms_message("Hacking speaker state: do magic from LinphoneCoreImpl.RouteAudioToSpeakerHelper()");
jni_env->CallVoidMethod(lc, routeAudioToSpeakerHelper_id, speakerOn);
// Re-open audio and set d->started=true
ms_message("Hacking speaker state: calling sound_read_preprocess()");
sound_read_preprocess(hackLastSoundReadFilter);
sound_read_preprocess(f);
return 0;
}
/******* End Hack for Galaxy S ***********/
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment