Commit af873b92 authored by Andrea Gianarda's avatar Andrea Gianarda

Implement audio routes in AAudio

parent e96fdafd
/*
* Copyright (c) 2010-2020 Belledonne Communications SARL.
*
* aaudio.h - Header file of Android Media plugin for Linphone, based on AAudio APIs.
* msaaudio.h - Header file of Android Media plugin for Linphone, based on AAudio APIs.
*
* 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
......@@ -20,20 +20,24 @@
#ifndef ms_aaudio_h
#define ms_aaudio_h
#include <aaudio/AAudio.h>
#include <mediastreamer2/android_utils.h>
#include <mediastreamer2/mssndcard.h>
static int DeviceFavoriteSampleRate = 44100;
extern int DeviceFavoriteSampleRate;
struct AAudioContext {
AAudioContext() {
samplerate = DeviceFavoriteSampleRate;
nchannels = 1;
builtin_aec = false;
device_changed = false;
}
int samplerate;
int nchannels;
bool builtin_aec;
bool device_changed;
};
MSFilter *android_snd_card_create_reader(MSSndCard *card);
......
/*
* Copyright (c) 2010-2019 Belledonne Communications SARL.
*
* androidsound_aaudio.cpp - Android Media plugin for Linphone, based on AAudio APIs.
* msaaudio.cpp - Android Media plugin for Linphone, based on AAudio APIs.
*
* 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
......@@ -19,63 +19,46 @@
#include <mediastreamer2/msjava.h>
#include <mediastreamer2/devices.h>
#include <mediastreamer2/android_utils.h>
#include <sys/types.h>
#include <jni.h>
#include <dlfcn.h>
#include <aaudio/AAudio.h>
#include <msaaudio/msaaudio.h>
static MSSndCard* android_snd_card_new(MSSndCardManager *m);
static void android_snd_card_device_create(JNIEnv *env, jobject deviceInfo, MSSndCardManager *m);
static AAudioContext* aaudio_context_init() {
AAudioContext* ctx = new AAudioContext();
return ctx;
}
// this global variable is shared among all msaaudio files
int DeviceFavoriteSampleRate = 44100;
aaudio_result_t initAAudio() {
// Initialize to AAUDIO_ERROR_BASE to ensure that the default value is an error condition
aaudio_result_t result = AAUDIO_ERROR_BASE;
void *handle;
static void android_snd_card_detect(MSSndCardManager *m) {
if ((handle = dlopen("libaaudio.so", RTLD_NOW)) == NULL){
ms_warning("[AAudio] Fail to load libAAudio : %s", dlerror());
result = AAUDIO_ERROR_BASE;
} else {
dlerror(); // Clear previous message if present
JNIEnv *env = ms_get_jni_env();
AAudioStreamBuilder *builder;
result = AAudio_createStreamBuilder(&builder);
if (result != AAUDIO_OK && !builder) {
ms_error("[AAudio] Couldn't create stream builder: %i / %s", result, AAudio_convertResultToText(result));
}
}
return result;
}
// Get all devices
jobject devices = get_all_devices(env, "all");
static void android_snd_card_detect(MSSndCardManager *m) {
SoundDeviceDescription* d = NULL;
MSDevicesInfo *devices = NULL;
aaudio_result_t initResult = initAAudio();
if (initResult == AAUDIO_OK) {
devices = ms_factory_get_devices_info(m->factory);
d = ms_devices_info_get_sound_device_description(devices);
MSSndCard *card = android_snd_card_new(m);
ms_snd_card_manager_prepend_card(m, card);
} else {
ms_warning("[AAudio] Failed to dlopen libAAudio, AAudio MS soundcard unavailable - Initialization exited with the following error code %i / %s", initResult, AAudio_convertResultToText(initResult));
// extract required information from every device
jobjectArray deviceArray = (jobjectArray) devices;
jsize deviceNumber = (int) env->GetArrayLength(deviceArray);
ms_message("[AAudio] Create soundcards for %0d devices", deviceNumber);
for (int idx=0; idx < deviceNumber; idx++) {
jobject deviceInfo = env->GetObjectArrayElement(deviceArray, idx);
android_snd_card_device_create(env, deviceInfo, m);
}
}
static void android_native_snd_card_init(MSSndCard *card) {
AAudioContext* context = new AAudioContext();
card->data = context;
}
static void android_native_snd_card_uninit(MSSndCard *card) {
AAudioContext *ctx = (AAudioContext*)card->data;
ms_warning("[AAudio] Deletion of AAudio context [%p]", ctx);
delete ctx;
}
MSSndCardDesc android_native_snd_aaudio_card_desc = {
......@@ -92,28 +75,69 @@ MSSndCardDesc android_native_snd_aaudio_card_desc = {
android_native_snd_card_uninit
};
static MSSndCard* android_snd_card_new(MSSndCardManager *m) {
MSSndCard* card = NULL;
SoundDeviceDescription *d = NULL;
MSDevicesInfo *devices = NULL;
static void android_snd_card_device_create(JNIEnv *env, jobject deviceInfo, MSSndCardManager *m) {
MSSndCardDeviceType type = get_device_type(env, deviceInfo);
if (
(type == MSSndCardDeviceType::MS_SND_CARD_DEVICE_TYPE_BLUETOOTH) ||
(type == MSSndCardDeviceType::MS_SND_CARD_DEVICE_TYPE_EARPIECE) ||
(type == MSSndCardDeviceType::MS_SND_CARD_DEVICE_TYPE_SPEAKER) ||
(type == MSSndCardDeviceType::MS_SND_CARD_DEVICE_TYPE_MICROPHONE) ||
(type == MSSndCardDeviceType::MS_SND_CARD_DEVICE_TYPE_HEADSET) ||
(type == MSSndCardDeviceType::MS_SND_CARD_DEVICE_TYPE_HEADPHONES) ||
(type == MSSndCardDeviceType::MS_SND_CARD_DEVICE_TYPE_GENERIC_USB)
) {
MSSndCard *card = ms_snd_card_new(&android_native_snd_aaudio_card_desc);
card->name = ms_strdup(get_device_product_name(env, deviceInfo));
card->internal_id = get_device_id(env, deviceInfo);
card->device_type = type;
AAudioContext *card_data = (AAudioContext*)card->data;
// Card capabilities
// Assign the value because the default value is MS_SND_CARD_CAP_CAPTURE|MS_SND_CARD_CAP_PLAYBACK
card->capabilities = get_device_capabilities(env, deviceInfo);
MSDevicesInfo *devices = ms_factory_get_devices_info(m->factory);
SoundDeviceDescription *d = ms_devices_info_get_sound_device_description(devices);
if (d->flags & DEVICE_HAS_BUILTIN_AEC) {
card->capabilities |= MS_SND_CARD_CAP_BUILTIN_ECHO_CANCELLER;
card_data->builtin_aec = true;
}
card = ms_snd_card_new(&android_native_snd_aaudio_card_desc);
card->name = ms_strdup("android aaudio sound card");
card->latency = d->delay;
if (d->recommended_rate){
card_data->samplerate = d->recommended_rate;
}
devices = ms_factory_get_devices_info(m->factory);
d = ms_devices_info_get_sound_device_description(devices);
// Take capabilities into account as the same device type may have different components with different capabilities and IDs
if(!ms_snd_card_is_card_duplicate(m, card, TRUE)) {
card=ms_snd_card_ref(card);
ms_snd_card_manager_prepend_card(m, card);
AAudioContext *context = aaudio_context_init();
if (d->flags & DEVICE_HAS_BUILTIN_AEC) {
card->capabilities |= MS_SND_CARD_CAP_BUILTIN_ECHO_CANCELLER;
context->builtin_aec = true;
ms_message("[AAudio] Added card: id %s name %s device ID %0d device_type %s capabilities 0'h%0X ", card->id, card->name, card->internal_id, ms_snd_card_device_type_to_string(card->device_type), card->capabilities);
}
}
card->latency = d->delay;
card->data = context;
if (d->recommended_rate){
context->samplerate = d->recommended_rate;
}
static bool loadLib() {
void *handle;
const char * libname = "libaaudio.so";
bool success = false;
// open library
if ((handle = dlopen(libname, RTLD_NOW)) == NULL){
ms_warning("[AAudio] Fail to load %s : %s", libname, dlerror());
success = false;
} else {
dlerror(); // Clear previous message if present
ms_message("[AAudio] %s successfully loaded", libname);
success = true;
}
return card;
return success;
}
#ifdef _MSC_VER
......@@ -126,23 +150,14 @@ static MSSndCard* android_snd_card_new(MSSndCardManager *m) {
MS_PLUGIN_DECLARE(void) libmsaaudio_init(MSFactory* factory) {
register_aaudio_player(factory);
register_aaudio_recorder(factory);
ms_message("[AAudio] libmsaaudio plugin loaded");
JNIEnv *env = ms_get_jni_env();
jclass mediastreamerAndroidContextClass = env->FindClass("org/linphone/mediastream/MediastreamerAndroidContext");
if (mediastreamerAndroidContextClass != NULL) {
jmethodID getSampleRate = env->GetStaticMethodID(mediastreamerAndroidContextClass, "getDeviceFavoriteSampleRate", "()I");
if (getSampleRate != NULL) {
jint ret = env->CallStaticIntMethod(mediastreamerAndroidContextClass, getSampleRate);
DeviceFavoriteSampleRate = (int)ret;
ms_message("[AAudio] Using %i for sample rate value", DeviceFavoriteSampleRate);
}
env->DeleteLocalRef(mediastreamerAndroidContextClass);
}
DeviceFavoriteSampleRate = get_preferred_sample_rate();
const bool loadOk = loadLib();
aaudio_result_t initResult = initAAudio();
if (initResult == AAUDIO_OK) {
if (loadOk) {
MSDevicesInfo* devices = ms_factory_get_devices_info(factory);
SoundDeviceDescription* d = ms_devices_info_get_sound_device_description(devices);
......@@ -152,10 +167,12 @@ MS_PLUGIN_DECLARE(void) libmsaaudio_init(MSFactory* factory) {
}
MSSndCardManager *m = ms_factory_get_snd_card_manager(factory);
MSSndCard *card = android_snd_card_new(m);
ms_snd_card_manager_prepend_card(m, card);
// Register card manager so that it can be automaticallty initialized
ms_snd_card_manager_register_desc(m, &android_native_snd_aaudio_card_desc);
ms_message("[AAudio] Soundcard created");
} else {
ms_warning("[AAudio] AAudio MS soundcard unavailable - Initialization exited with the following error code %i / %s", initResult, AAudio_convertResultToText(initResult));
ms_error("[AAudio] Unable to load AAudio plugin shared object");
}
}
......@@ -20,7 +20,6 @@
#include <string.h>
#include "mediastreamer2/msjava.h"
#include <aaudio/AAudio.h>
#include <msaaudio/msaaudio.h>
static const int flowControlIntervalMs = 5000;
......@@ -28,15 +27,12 @@ static const int flowControlThresholdMs = 40;
static void aaudio_player_callback_error(AAudioStream *stream, void *userData, aaudio_result_t error);
static int32_t getUpdatedDeviceId();
struct AAudioOutputContext {
AAudioOutputContext(MSFilter *f) {
mFilter = f;
ms_flow_controlled_bufferizer_init(&buffer, f, DeviceFavoriteSampleRate, 1);
ms_mutex_init(&mutex, NULL);
ms_mutex_init(&stream_mutex, NULL);
deviceId = AAUDIO_UNSPECIFIED;
soundCard = NULL;
usage = AAUDIO_USAGE_VOICE_COMMUNICATION;
content_type = AAUDIO_CONTENT_TYPE_SPEECH;
......@@ -100,7 +96,6 @@ struct AAudioOutputContext {
ms_mutex_t mutex;
aaudio_usage_t usage;
aaudio_content_type_t content_type;
int32_t deviceId;
int32_t bufferCapacity;
int32_t prevXRunCount;
......@@ -114,7 +109,11 @@ static void android_snd_write_init(MSFilter *obj){
}
static void android_snd_write_uninit(MSFilter *obj){
AAudioOutputContext *octx = (AAudioOutputContext*)obj->data;
AAudioOutputContext *octx = static_cast<AAudioOutputContext*>(obj->data);
if (octx->soundCard) {
ms_snd_card_unref(octx->soundCard);
octx->soundCard = NULL;
}
delete octx;
}
......@@ -124,14 +123,14 @@ static int android_snd_write_set_sample_rate(MSFilter *obj, void *data) {
static int android_snd_write_get_sample_rate(MSFilter *obj, void *data) {
int *n = (int*)data;
AAudioOutputContext *octx = (AAudioOutputContext*)obj->data;
AAudioOutputContext *octx = static_cast<AAudioOutputContext*>(obj->data);
*n = octx->aaudio_context->samplerate;
return 0;
}
static int android_snd_write_set_nchannels(MSFilter *obj, void *data) {
int *n = (int*)data;
AAudioOutputContext *octx = (AAudioOutputContext*)obj->data;
AAudioOutputContext *octx = static_cast<AAudioOutputContext*>(obj->data);
octx->aaudio_context->nchannels = *n;
ms_flow_controlled_bufferizer_set_nchannels(&octx->buffer, octx->aaudio_context->nchannels);
return 0;
......@@ -139,11 +138,40 @@ static int android_snd_write_set_nchannels(MSFilter *obj, void *data) {
static int android_snd_write_get_nchannels(MSFilter *obj, void *data) {
int *n = (int*)data;
AAudioOutputContext *octx = (AAudioOutputContext*)obj->data;
AAudioOutputContext *octx = static_cast<AAudioOutputContext*>(obj->data);
*n = octx->aaudio_context->nchannels;
return 0;
}
static int android_snd_write_set_device_id(MSFilter *obj, void *data) {
MSSndCard *card = (MSSndCard*)data;
AAudioOutputContext *octx = static_cast<AAudioOutputContext*>(obj->data);
ms_message("[AAudio] Requesting to output card. Current %s (device ID %0d) and requested %s (device ID %0d)", ms_snd_card_get_string_id(octx->soundCard), octx->soundCard->internal_id, ms_snd_card_get_string_id(card), card->internal_id);
// Change device ID only if the new value is different from the previous one
if (octx->soundCard->internal_id != card->internal_id) {
ms_mutex_lock(&octx->stream_mutex);
if (octx->soundCard) {
ms_snd_card_unref(octx->soundCard);
octx->soundCard = NULL;
}
octx->soundCard = ms_snd_card_ref(card);
octx->aaudio_context->device_changed = true;
JNIEnv *env = ms_get_jni_env();
set_bt_enable(env, (ms_snd_card_get_device_type(octx->soundCard) == MSSndCardDeviceType::MS_SND_CARD_DEVICE_TYPE_BLUETOOTH));
ms_mutex_unlock(&octx->stream_mutex);
}
return 0;
}
static int android_snd_write_get_device_id(MSFilter *obj, void *data) {
int *n = (int*)data;
AAudioOutputContext *octx = (AAudioOutputContext*)obj->data;
*n = octx->soundCard->internal_id;
return 0;
}
static aaudio_data_callback_result_t aaudio_player_callback(AAudioStream *stream, void *userData, void *audioData, int32_t numFrames) {
AAudioOutputContext *octx = (AAudioOutputContext*)userData;
......@@ -166,10 +194,6 @@ static aaudio_data_callback_result_t aaudio_player_callback(AAudioStream *stream
return AAUDIO_CALLBACK_RESULT_CONTINUE;
}
void setDeviceIdInStreamBuilder(AAudioOutputContext *octx, AAudioStreamBuilder *builder) {
AAudioStreamBuilder_setDeviceId(builder, octx->deviceId);
}
static void aaudio_player_init(AAudioOutputContext *octx) {
AAudioStreamBuilder *builder;
aaudio_result_t result = AAudio_createStreamBuilder(&builder);
......@@ -178,7 +202,7 @@ static void aaudio_player_init(AAudioOutputContext *octx) {
}
octx->updateStreamTypeFromMsSndCard();
setDeviceIdInStreamBuilder(octx, builder);
AAudioStreamBuilder_setDeviceId(builder, octx->soundCard->internal_id);
AAudioStreamBuilder_setDirection(builder, AAUDIO_DIRECTION_OUTPUT);
AAudioStreamBuilder_setSampleRate(builder, octx->aaudio_context->samplerate);
AAudioStreamBuilder_setDataCallback(builder, aaudio_player_callback, octx);
......@@ -196,11 +220,17 @@ static void aaudio_player_init(AAudioOutputContext *octx) {
if (result != AAUDIO_OK && !octx->stream) {
ms_error("[AAudio] Open stream for player failed: %i / %s", result, AAudio_convertResultToText(result));
AAudioStreamBuilder_delete(builder);
octx->stream = NULL;
return;
} else {
ms_message("[AAudio] Player stream opened");
}
aaudio_content_type_t contentType = AAudioStream_getContentType(octx->stream);
aaudio_usage_t usage = AAudioStream_getUsage(octx->stream);
ms_message("[AAudio] Expected content type %i, got %i", octx->content_type, contentType);
ms_message("[AAudio] Expected usage %i, got %i", octx->usage, usage);
octx->framesPerBurst = AAudioStream_getFramesPerBurst(octx->stream);
// Set the buffer size to the burst size - this will give us the minimum possible latency
AAudioStream_setBufferSizeInFrames(octx->stream, octx->framesPerBurst * octx->aaudio_context->nchannels);
......@@ -225,8 +255,6 @@ static void aaudio_player_init(AAudioOutputContext *octx) {
ms_message("[AAudio] Player stream started");
}
int32_t xRunCount = AAudioStream_getXRunCount(octx->stream);
AAudioStreamBuilder_delete(builder);
}
......@@ -259,29 +287,35 @@ static void aaudio_player_callback_error(AAudioStream *stream, void *userData, a
static void android_snd_write_preprocess(MSFilter *obj) {
AAudioOutputContext *octx = (AAudioOutputContext*)obj->data;
aaudio_player_init(octx);
JNIEnv *env = ms_get_jni_env();
set_bt_enable(env, (ms_snd_card_get_device_type(octx->soundCard) == MSSndCardDeviceType::MS_SND_CARD_DEVICE_TYPE_BLUETOOTH));
}
static void android_snd_adjust_buffer_size(AAudioOutputContext *octx) {
int32_t xRunCount = AAudioStream_getXRunCount(octx->stream);
// Ensure that stream has been created before adjusting buffer size
if (octx->stream) {
int32_t xRunCount = AAudioStream_getXRunCount(octx->stream);
// If underrunning is gettting worse
if (xRunCount > octx->prevXRunCount) {
// If underrunning is getting worse
if (xRunCount > octx->prevXRunCount) {
// New buffer size
int32_t newBufferSize = octx->bufferSize + octx->framesPerBurst;
// New buffer size
int32_t newBufferSize = octx->bufferSize + octx->framesPerBurst;
// Buffer size cannot be bigger than the buffer capacity and it must be larger than 0
if (octx->bufferCapacity < newBufferSize) {
newBufferSize = octx->bufferCapacity;
} else if (newBufferSize <= 0) {
newBufferSize = 1;
}
// Buffer size cannot be bigger than the buffer capacity and it must be larger than 0
if (octx->bufferCapacity < newBufferSize) {
newBufferSize = octx->bufferCapacity;
} else if (newBufferSize <= 0) {
newBufferSize = 1;
}
ms_message("[AAudio] xRunCount %0d - Changing buffer size from %0d to %0d frames (maximum capacity %0d frames)", xRunCount, octx->bufferSize, newBufferSize, octx->bufferCapacity);
AAudioStream_setBufferSizeInFrames(octx->stream, newBufferSize);
ms_message("[AAudio] xRunCount %0d - Changing buffer size from %0d to %0d frames (maximum capacity %0d frames)", xRunCount, octx->bufferSize, newBufferSize, octx->bufferCapacity);
AAudioStream_setBufferSizeInFrames(octx->stream, newBufferSize);
octx->bufferSize = newBufferSize;
octx->prevXRunCount = xRunCount;
octx->bufferSize = newBufferSize;
octx->prevXRunCount = xRunCount;
}
}
}
......@@ -290,6 +324,15 @@ static void android_snd_write_process(MSFilter *obj) {
ms_mutex_lock(&octx->stream_mutex);
if (octx->aaudio_context->device_changed) {
ms_warning("[AAudio] Device ID changed to %0d", octx->soundCard->internal_id);
if (octx->stream) {
AAudioStream_close(octx->stream);
octx->stream = NULL;
}
octx->aaudio_context->device_changed = false;
}
if (!octx->stream) {
aaudio_player_init(octx);
} else {
......@@ -315,6 +358,9 @@ static void android_snd_write_process(MSFilter *obj) {
static void android_snd_write_postprocess(MSFilter *obj) {
AAudioOutputContext *octx = (AAudioOutputContext*)obj->data;
aaudio_player_close(octx);
// At the end of a call, postprocess is called therefore here the bluetooth device is disabled
JNIEnv *env = ms_get_jni_env();
set_bt_enable(env, FALSE);
}
static MSFilterMethod android_snd_write_methods[] = {
......@@ -322,6 +368,8 @@ static MSFilterMethod android_snd_write_methods[] = {
{MS_FILTER_GET_SAMPLE_RATE, android_snd_write_get_sample_rate},
{MS_FILTER_SET_NCHANNELS, android_snd_write_set_nchannels},
{MS_FILTER_GET_NCHANNELS, android_snd_write_get_nchannels},
{MS_AUDIO_PLAYBACK_SET_INTERNAL_ID, android_snd_write_set_device_id},
{MS_AUDIO_PLAYBACK_GET_INTERNAL_ID, android_snd_write_get_device_id},
{0,NULL}
};
......@@ -354,7 +402,7 @@ static MSFilter* ms_android_snd_write_new(MSFactory* factory) {
MSFilter *android_snd_card_create_writer(MSSndCard *card) {
MSFilter *f = ms_android_snd_write_new(ms_snd_card_get_factory(card));
AAudioOutputContext *octx = static_cast<AAudioOutputContext*>(f->data);
octx->soundCard = card;
octx->soundCard = ms_snd_card_ref(card);
octx->setContext((AAudioContext*)card->data);
return f;
}
/*
* Copyright (c) 2010-2020 Belledonne Communications SARL.
*
* aaudio_recorder.cpp - Android Media Recorder plugin for Linphone, based on AAudio APIs.
* msaaudio_recorder.cpp - Android Media Recorder plugin for Linphone, based on AAudio APIs.
*
* 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
......@@ -19,9 +19,7 @@
#include <mediastreamer2/msjava.h>
#include <mediastreamer2/msticker.h>
#include <mediastreamer2/android_utils.h>
#include <aaudio/AAudio.h>
#include <msaaudio/msaaudio.h>
struct AAudioInputContext {
......@@ -31,7 +29,6 @@ struct AAudioInputContext {
ms_mutex_init(&stream_mutex, NULL);
mTickerSynchronizer = NULL;
mAvSkew = 0;
deviceId = AAUDIO_UNSPECIFIED;
session_id = AAUDIO_SESSION_ID_NONE;
soundCard = NULL;
aec = NULL;
......@@ -59,7 +56,6 @@ struct AAudioInputContext {
int64_t read_samples;
int32_t samplesPerFrame;
double mAvSkew;
int32_t deviceId;
aaudio_session_id_t session_id;
jobject aec;
};
......@@ -110,7 +106,9 @@ static void aaudio_recorder_init(AAudioInputContext *ictx) {
ms_error("[AAudio] Couldn't create stream builder for recorder: %i / %s", result, AAudio_convertResultToText(result));
}
AAudioStreamBuilder_setDeviceId(builder, ictx->deviceId);
ms_message("[AAudio] DEBUG Creating input stream for device ID %0d", ictx->soundCard->internal_id);
AAudioStreamBuilder_setDeviceId(builder, ictx->soundCard->internal_id);
AAudioStreamBuilder_setDirection(builder, AAUDIO_DIRECTION_INPUT);
AAudioStreamBuilder_setSampleRate(builder, ictx->aaudio_context->samplerate);
AAudioStreamBuilder_setDataCallback(builder, aaudio_recorder_callback, ictx);
......@@ -134,6 +132,7 @@ static void aaudio_recorder_init(AAudioInputContext *ictx) {
if (result != AAUDIO_OK && !ictx->stream) {
ms_error("[AAudio] Open stream for recorder failed: %i / %s", result, AAudio_convertResultToText(result));
AAudioStreamBuilder_delete(builder);
ictx->stream = NULL;
return;
} else {
ms_message("[AAudio] Recorder stream opened");
......@@ -204,6 +203,9 @@ static void android_snd_read_preprocess(MSFilter *obj) {
ictx->mFilter = obj;
ictx->read_samples = 0;
aaudio_recorder_init(ictx);
JNIEnv *env = ms_get_jni_env();
set_bt_enable(env, (ms_snd_card_get_device_type(ictx->soundCard) == MSSndCardDeviceType::MS_SND_CARD_DEVICE_TYPE_BLUETOOTH));
}
static void android_snd_read_process(MSFilter *obj) {
......@@ -211,6 +213,17 @@ static void android_snd_read_process(MSFilter *obj) {
mblk_t *m;
ms_mutex_lock(&ictx->stream_mutex);
if (ictx->aaudio_context->device_changed) {
ms_warning("[AAudio] Device ID changed to %0d", ictx->soundCard->internal_id);
if (ictx->stream) {
AAudioStream_close(ictx->stream);
ictx->stream = NULL;
}
ictx->aaudio_context->device_changed = false;
}
if (!ictx->stream) {
aaudio_recorder_init(ictx);
} else {
......@@ -237,25 +250,33 @@ static void android_snd_read_process(MSFilter *obj) {
static void android_snd_read_postprocess(MSFilter *obj) {
AAudioInputContext *ictx = (AAudioInputContext*)obj->data;
aaudio_recorder_close(ictx);
aaudio_recorder_close(ictx);
ms_ticker_set_synchronizer(obj->ticker, NULL);
ms_mutex_lock(&ictx->mutex);
ms_ticker_synchronizer_destroy(ictx->mTickerSynchronizer);
ictx->mTickerSynchronizer = NULL;
JNIEnv *env = ms_get_jni_env();
if (ictx->aec) {
JNIEnv *env = ms_get_jni_env();
ms_android_delete_hardware_echo_canceller(env, ictx->aec);
ictx->aec = NULL;
ms_message("[AAudio] Hardware echo canceller deleted");
}
set_bt_enable(env, FALSE);
ms_mutex_unlock(&ictx->mutex);
}
static void android_snd_read_uninit(MSFilter *obj) {
AAudioInputContext *ictx = (AAudioInputContext*)obj->data;
AAudioInputContext *ictx = static_cast<AAudioInputContext*>(obj->data);
if (ictx->soundCard) {
ms_snd_card_unref(ictx->soundCard);
ictx->soundCard = NULL;
}
delete ictx;
}
......@@ -265,25 +286,53 @@ static int android_snd_read_set_sample_rate(MSFilter *obj, void *data) {
static int android_snd_read_get_sample_rate(MSFilter *obj, void *data) {
int *n = (int*)data;
AAudioInputContext *ictx = (AAudioInputContext*)obj->data;
AAudioInputContext *ictx = static_cast<AAudioInputContext*>(obj->data);
*n = ictx->aaudio_context->samplerate;
return 0;
}
static int android_snd_read_set_nchannels(MSFilter *obj, void *data) {
int *n = (int*)data;
AAudioInputContext *ictx = (AAudioInputContext*)obj->data;
AAudioInputContext *ictx = static_cast<AAudioInputContext*>(obj->data);
ictx->aaudio_context->nchannels = *n;
return 0;
}
static int android_snd_read_get_nchannels(MSFilter *obj, void *data) {
int *n = (int*)data;
AAudioInputContext *ictx = (AAudioInputContext*)obj->data;
AAudioInputContext *ictx = static_cast<AAudioInputContext*>(obj->data);
*n = ictx->aaudio_context->nchannels;
return 0;
}
static int android_snd_read_set_device_id(MSFilter *obj, void *data) {
MSSndCard *card = (MSSndCard*)data;
AAudioInputContext *ictx = static_cast<AAudioInputContext*>(obj->data);
ms_message("[AAudio] Requesting to change capture device ID from %0d to %0d", ictx->soundCard->internal_id, card->internal_id);
// Change device ID only if the new value is different from the previous one
if (ictx->soundCard->internal_id != card->internal_id) {
ms_mutex_lock(&ictx->stream_mutex);
if (ictx->soundCard) {
ms_snd_card_unref(ictx->soundCard);
ictx->soundCard = NULL;
}
ictx->soundCard = ms_snd_card_ref(card);
ictx->aaudio_context->device_changed = true;
JNIEnv *env = ms_get_jni_env();
set_bt_enable(env, (ms_snd_card_get_device_type(ictx->soundCard) == MSSndCardDeviceType::MS_SND_CARD_DEVICE_TYPE_BLUETOOTH));
ms_mutex_unlock(&ictx->stream_mutex);
}
return 0;
}
static int android_snd_read_get_device_id(MSFilter *obj, void *data) {
int *n = (int*)data;
AAudioInputContext *ictx = (AAudioInputContext*)obj->data;
*n = ictx->soundCard->internal_id;
return 0;
}
static int android_snd_read_hack_speaker_state(MSFilter *f, void *arg) {
return 0;
}
......@@ -294,6 +343,8 @@ static MSFilterMethod android_snd_read_methods[] = {
{MS_FILTER_SET_NCHANNELS, android_snd_read_set_nchannels},
{MS_FILTER_GET_NCHANNELS, android_snd_read_get_nchannels},
{MS_AUDIO_CAPTURE_FORCE_SPEAKER_STATE, android_snd_read_hack_speaker_state},
{MS_AUDIO_CAPTURE_SET_INTERNAL_ID, android_snd_read_set_device_id},
{MS_AUDIO_CAPTURE_GET_INTERNAL_ID, android_snd_read_get_device_id},
{0,NULL}
};
......@@ -325,9 +376,10 @@ static MSFilter* ms_android_snd_read_new(MSFactory *factory) {
MSFilter *android_snd_card_create_reader(MSSndCard *card) {
ms_message("[AAudio] DEBUG Setting capture card to: id %s name %s device ID %0d device_type %s capabilities 0'h%0X", card->id, card->name, card->internal_id, ms_snd_card_device_type_to_string(card->device_type), card->capabilities);
MSFilter *f = ms_android_snd_read_new(ms_snd_card_get_factory(card));
AAudioInputContext *ictx = static_cast<AAudioInputContext*>(f->data);
ictx->soundCard = card;
ictx->soundCard = ms_snd_card_ref(card);
ictx->setContext((AAudioContext*)card->data);
return f;
}
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