Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 64050172 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "audio-hal: use audio source to get delay latency"

parents 8e9dcf8d 918e1e1c
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -952,10 +952,10 @@ static int qaf_get_rendered_frames(struct stream_out *out, uint64_t *frames)

        if (qaf_mod->stream_out[QAF_OUT_OFFLOAD])
            platform_latency =
                platform_render_latency(qaf_mod->stream_out[QAF_OUT_OFFLOAD]->usecase);
                platform_render_latency(qaf_mod->stream_out[QAF_OUT_OFFLOAD]);
        else
            platform_latency =
                platform_render_latency(qaf_mod->stream_out[QAF_OUT_OFFLOAD_MCH]->usecase);
                platform_render_latency(qaf_mod->stream_out[QAF_OUT_OFFLOAD_MCH]);

        dsp_latency = (platform_latency * sample_rate) / 1000000LL;
    } else if (qaf_mod->stream_out[QAF_OUT_TRANSCODE_PASSTHROUGH] != NULL) {
+29 −13
Original line number Diff line number Diff line
@@ -186,6 +186,8 @@ do {\
#define SVA_PARAM_CHANNEL_INDEX "st_channel_index"
#define MAX_STR_LENGTH_FFV_PARAMS 30
#define MAX_FFV_SESSION_ID 100

#define ST_DEVICE SND_DEVICE_IN_HANDSET_MIC
/*
 * Current proprietary API version used by AHAL. Queried by STHAL
 * for compatibility check with AHAL
@@ -254,7 +256,8 @@ static int populate_usecase(struct audio_hal_usecase *usecase,
        break;

    case PCM_CAPTURE:
        if (uc_info->id == USECASE_AUDIO_RECORD_VOIP)
        if (uc_info->stream.in != NULL &&
             uc_info->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
            usecase->type = USECASE_TYPE_VOIP_CALL;
        else
            usecase->type = USECASE_TYPE_PCM_CAPTURE;
@@ -474,14 +477,7 @@ void audio_extn_sound_trigger_check_and_get_session(struct stream_in *in)

bool is_same_as_st_device(snd_device_t snd_device)
{
    if (snd_device == SND_DEVICE_IN_HANDSET_MIC_AEC ||
        snd_device == SND_DEVICE_IN_HANDSET_MIC ||
        snd_device == SND_DEVICE_IN_HANDSET_MIC_AEC_NS ||
        snd_device == SND_DEVICE_IN_SPEAKER_MIC ||
        snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC ||
        snd_device == SND_DEVICE_IN_SPEAKER_MIC_AEC ||
        snd_device == SND_DEVICE_IN_SPEAKER_MIC_AEC_NS ||
        snd_device == SND_DEVICE_IN_SPEAKER_MIC_NS) {
    if (platform_check_all_backends_match(ST_DEVICE, snd_device)) {
        ALOGD("audio HAL using same device %d as ST", snd_device);
        return true;
    }
@@ -529,32 +525,52 @@ void audio_extn_sound_trigger_update_device_status(snd_device_t snd_device,
{
    bool raise_event = false;
    int device_type = -1;
    struct audio_event_info ev_info;

    ev_info.u.usecase.type = -1;

    if (!st_dev)
       return;

    list_init(&ev_info.device_info.devices);

    if (snd_device >= SND_DEVICE_OUT_BEGIN &&
        snd_device < SND_DEVICE_OUT_END)
        device_type = PCM_PLAYBACK;
    else if (snd_device >= SND_DEVICE_IN_BEGIN &&
        snd_device < SND_DEVICE_IN_END)
        snd_device < SND_DEVICE_IN_END) {
        device_type = PCM_CAPTURE;
    else {
        if (is_same_as_st_device(snd_device))
            update_device_list(&ev_info.device_info.devices, ST_DEVICE_HANDSET_MIC, "", true);
    } else {
        ALOGE("%s: invalid device 0x%x, for event %d",
                           __func__, snd_device, event);
        return;
    }

    struct stream_in *active_input = adev_get_active_input(st_dev->adev);
    audio_source_t  source = (active_input == NULL) ?
                               AUDIO_SOURCE_DEFAULT : active_input->source;
    if (st_dev->adev->mode == AUDIO_MODE_IN_CALL) {
        ev_info.u.usecase.type = USECASE_TYPE_VOICE_CALL;
    } else if ((st_dev->adev->mode == AUDIO_MODE_IN_COMMUNICATION ||
                source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
               active_input) {
        ev_info.u.usecase.type  = USECASE_TYPE_VOIP_CALL;
    } else if (device_type == PCM_CAPTURE) {
        ev_info.u.usecase.type  = USECASE_TYPE_PCM_CAPTURE;
    }

    raise_event = platform_sound_trigger_device_needs_event(snd_device);
    ALOGI("%s: device 0x%x of type %d for Event %d, with Raise=%d",
        __func__, snd_device, device_type, event, raise_event);
    if (raise_event && (device_type == PCM_CAPTURE)) {
        switch(event) {
        case ST_EVENT_SND_DEVICE_FREE:
            st_dev->st_callback(AUDIO_EVENT_CAPTURE_DEVICE_INACTIVE, NULL);
            st_dev->st_callback(AUDIO_EVENT_CAPTURE_DEVICE_INACTIVE, &ev_info);
            break;
        case ST_EVENT_SND_DEVICE_BUSY:
            st_dev->st_callback(AUDIO_EVENT_CAPTURE_DEVICE_ACTIVE, NULL);
            st_dev->st_callback(AUDIO_EVENT_CAPTURE_DEVICE_ACTIVE, &ev_info);
            break;
        default:
            ALOGW("%s:invalid event %d for device 0x%x",
+14 −4
Original line number Diff line number Diff line
@@ -4297,8 +4297,10 @@ static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct ti
    /* This adjustment accounts for buffering after app processor.
     * It is based on estimated DSP latency per use case, rather than exact.
     */
    int64_t platform_latency =  platform_render_latency(out->usecase) *
    pthread_mutex_lock(&adev->lock);
    int64_t platform_latency =  platform_render_latency(out->dev, out->usecase) *
                                out->sample_rate / 1000000LL;
    pthread_mutex_unlock(&adev->lock);

    pthread_mutex_lock(&out->position_query_lock);
    /* not querying actual state of buffering in kernel as it would involve an ioctl call
@@ -5250,7 +5252,9 @@ static uint32_t out_get_latency(const struct audio_stream_out *stream)
                         1000) / (out->config.rate);
        else
            period_ms = 0;
        latency = period_ms + platform_render_latency(out->usecase)/1000;
        pthread_mutex_lock(&adev->lock);
        latency = period_ms + platform_render_latency(out->dev, out->usecase)/1000;
        pthread_mutex_unlock(&adev->lock);
    } else {
        latency = (out->config.period_count * out->config.period_size * 1000) /
           (out->config.rate);
@@ -6184,7 +6188,10 @@ static int out_get_presentation_position(const struct audio_stream_out *stream,

                // This adjustment accounts for buffering after app processor.
                // It is based on estimated DSP latency per use case, rather than exact.
                frames_temp = platform_render_latency(out->usecase) * out->sample_rate / 1000000LL;
                pthread_mutex_lock(&adev->lock);
                frames_temp = platform_render_latency(out->dev, out->usecase) *
                              out->sample_rate / 1000000LL;
                pthread_mutex_unlock(&adev->lock);
                if (signed_frames >= frames_temp)
                    signed_frames -= frames_temp;

@@ -7081,7 +7088,10 @@ static int in_get_capture_position(const struct audio_stream_in *stream,
        unsigned int avail;
        if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
            *frames = in->frames_read + avail;
            *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
            pthread_mutex_lock(&adev->lock);
            *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
                    - platform_capture_latency(in->dev, in->usecase) * 1000LL;
            pthread_mutex_unlock(&adev->lock);
            ret = 0;
        }
    }
+84 −7
Original line number Diff line number Diff line
@@ -1034,6 +1034,22 @@ static int msm_device_to_be_id_external_codec [][NO_COLS] = {
#define ULL_PLATFORM_DELAY (6*1000LL)
#define MMAP_PLATFORM_DELAY (3*1000LL)

static int audio_source_delay_ms[AUDIO_SOURCE_CNT] = {0};

static struct name_to_index audio_source_index[AUDIO_SOURCE_CNT] = {
    {TO_NAME_INDEX(AUDIO_SOURCE_DEFAULT)},
    {TO_NAME_INDEX(AUDIO_SOURCE_MIC)},
    {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_UPLINK)},
    {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_DOWNLINK)},
    {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_CALL)},
    {TO_NAME_INDEX(AUDIO_SOURCE_CAMCORDER)},
    {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_RECOGNITION)},
    {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_COMMUNICATION)},
    {TO_NAME_INDEX(AUDIO_SOURCE_REMOTE_SUBMIX)},
    {TO_NAME_INDEX(AUDIO_SOURCE_UNPROCESSED)},
    {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_PERFORMANCE)},
};

static const char *platform_get_mixer_control(struct mixer_ctl *);

static void update_interface(const char *snd_card_name) {
@@ -3215,6 +3231,11 @@ int platform_get_usecase_index(const char *usecase_name)
    return find_index(usecase_name_index, AUDIO_USECASE_MAX, usecase_name);
}

int platform_get_audio_source_index(const char *audio_source_name)
{
    return find_index(audio_source_index, AUDIO_SOURCE_CNT, audio_source_name);
}

int platform_get_effect_config_data(snd_device_t snd_device,
                                      struct audio_effect_config *effect_config,
                                      effect_type_t effect_type)
@@ -5767,24 +5788,80 @@ unsigned char* platform_get_license(void *platform __unused, int *size __unused)
}


void platform_set_snd_device_delay(snd_device_t snd_device __unused, int delay_ms __unused)
{
}

void platform_set_audio_source_delay(audio_source_t audio_source, int delay_ms)
{
    if ((audio_source < AUDIO_SOURCE_DEFAULT) ||
           (audio_source > AUDIO_SOURCE_MAX)) {
        ALOGE("%s: Invalid audio_source = %d", __func__, audio_source);
        return;
    }

    audio_source_delay_ms[audio_source] = delay_ms;
}

/* Delay in Us */
int64_t platform_get_audio_source_delay(audio_source_t audio_source)
{
    if ((audio_source < AUDIO_SOURCE_DEFAULT) ||
            (audio_source > AUDIO_SOURCE_MAX)) {
        ALOGE("%s: Invalid audio_source = %d", __func__, audio_source);
        return 0;
    }

    return 1000LL * audio_source_delay_ms[audio_source];
}

int64_t platform_capture_latency(struct audio_device *adev __unused,
                                 audio_usecase_t usecase)
{
}

/* Delay in Us, only to be used for PCM formats */
int64_t platform_render_latency(audio_usecase_t usecase)
int64_t platform_render_latency(struct audio_device *adev __unused,
                                audio_usecase_t usecase)
{
    int64_t delay = 0LL;

    switch (usecase) {
        case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER:
            return DEEP_BUFFER_PLATFORM_DELAY;
            delay = DEEP_BUFFER_PLATFORM_DELAY;
            break;
        case USECASE_AUDIO_PLAYBACK_LOW_LATENCY:
            return LOW_LATENCY_PLATFORM_DELAY;
            delay = LOW_LATENCY_PLATFORM_DELAY;
            break;
        case USECASE_AUDIO_PLAYBACK_OFFLOAD:
        case USECASE_AUDIO_PLAYBACK_OFFLOAD2:
            return PCM_OFFLOAD_PLATFORM_DELAY;
            delay = PCM_OFFLOAD_PLATFORM_DELAY;
            break;
        case USECASE_AUDIO_PLAYBACK_ULL:
            return ULL_PLATFORM_DELAY;
            delay = ULL_PLATFORM_DELAY;
            break;
        case USECASE_AUDIO_PLAYBACK_MMAP:
            return MMAP_PLATFORM_DELAY;
            delay = MMAP_PLATFORM_DELAY;
            break;
        default:
            return 0;
            break;
    }

    /* out->device could be used to add delay time if it's necessary */
    return delay;
}

int64_t platform_capture_latency(struct stream_in *in)
{
    int64_t delay = 0LL;

    if (!in)
        return delay;

    delay = platform_get_audio_source_delay(in->source);

    /* in->device could be used to add delay time if it's necessary */
    return delay;
}

int platform_update_usecase_from_source(int source, int usecase)
+110 −7
Original line number Diff line number Diff line
@@ -1520,12 +1520,30 @@ static int msm_be_id_array_len =
    sizeof(msm_device_to_be_id) / sizeof(msm_device_to_be_id[0]);
#endif

static int snd_device_delay_ms[SND_DEVICE_MAX] = {0};

#define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL)
#define PCM_OFFLOAD_PLATFORM_DELAY (30*1000LL)
#define LOW_LATENCY_PLATFORM_DELAY (13*1000LL)
#define ULL_PLATFORM_DELAY         (3*1000LL)
#define MMAP_PLATFORM_DELAY        (3*1000LL)

static int audio_source_delay_ms[AUDIO_SOURCE_CNT] = {0};

static struct name_to_index audio_source_index[AUDIO_SOURCE_CNT] = {
    {TO_NAME_INDEX(AUDIO_SOURCE_DEFAULT)},
    {TO_NAME_INDEX(AUDIO_SOURCE_MIC)},
    {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_UPLINK)},
    {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_DOWNLINK)},
    {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_CALL)},
    {TO_NAME_INDEX(AUDIO_SOURCE_CAMCORDER)},
    {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_RECOGNITION)},
    {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_COMMUNICATION)},
    {TO_NAME_INDEX(AUDIO_SOURCE_REMOTE_SUBMIX)},
    {TO_NAME_INDEX(AUDIO_SOURCE_UNPROCESSED)},
    {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_PERFORMANCE)},
};

static bool is_usb_snd_dev(snd_device_t snd_device)
{
    if (snd_device < SND_DEVICE_IN_BEGIN) {
@@ -2154,6 +2172,7 @@ static void set_platform_defaults(struct platform_data * my_data)
        hw_interface_table[dev] = NULL;
        operator_specific_device_table[dev] = NULL;
        external_specific_device_table[dev] = NULL;
        snd_device_delay_ms[dev] = 0;
    }
    for (dev = 0; dev < SND_DEVICE_MAX; dev++) {
        backend_bit_width_table[dev] = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
@@ -4647,6 +4666,11 @@ int platform_get_usecase_index(const char *usecase_name)
    return find_index(usecase_name_index, AUDIO_USECASE_MAX, usecase_name);
}

int platform_get_audio_source_index(const char *audio_source_name)
{
    return find_index(audio_source_index, AUDIO_SOURCE_CNT, audio_source_name);
}

void platform_add_operator_specific_device(snd_device_t snd_device,
                                           const char *operator,
                                           const char *mixer_path,
@@ -8602,31 +8626,110 @@ done:
    return NULL;
}

void platform_set_snd_device_delay(snd_device_t snd_device, int delay_ms)
{
    if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) {
        ALOGE("%s: Invalid snd_device = %d", __func__, snd_device);
        return;
    }

    snd_device_delay_ms[snd_device] = delay_ms;
}

/* return delay in Us */
int64_t platform_get_snd_device_delay(snd_device_t snd_device)
{
    if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) {
        ALOGE("%s: Invalid snd_device = %d", __func__, snd_device);
        return 0;
    }
    return 1000LL * (int64_t)snd_device_delay_ms[snd_device];
}

void platform_set_audio_source_delay(audio_source_t audio_source, int delay_ms)
{
    if ((audio_source < AUDIO_SOURCE_DEFAULT) ||
           (audio_source > AUDIO_SOURCE_MAX)) {
        ALOGE("%s: Invalid audio_source = %d", __func__, audio_source);
        return;
    }

    audio_source_delay_ms[audio_source] = delay_ms;
}

/* Delay in Us */
int64_t platform_get_audio_source_delay(audio_source_t audio_source)
{
    if ((audio_source < AUDIO_SOURCE_DEFAULT) ||
            (audio_source > AUDIO_SOURCE_MAX)) {
        ALOGE("%s: Invalid audio_source = %d", __func__, audio_source);
        return 0;
    }

    return 1000LL * audio_source_delay_ms[audio_source];
}

/* Delay in Us */
/* Delay in Us, only to be used for PCM formats */
int64_t platform_render_latency(audio_usecase_t usecase)
int64_t platform_render_latency(struct audio_device *adev, audio_usecase_t usecase)
{
    int64_t delay = 0LL;
    struct audio_usecase *uc_info;

    switch (usecase) {
        case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER:
        case USECASE_AUDIO_PLAYBACK_MEDIA:
        case USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE:
        case USECASE_AUDIO_PLAYBACK_REAR_SEAT:
            return DEEP_BUFFER_PLATFORM_DELAY;
            delay = DEEP_BUFFER_PLATFORM_DELAY;
            break;
        case USECASE_AUDIO_PLAYBACK_LOW_LATENCY:
        case USECASE_AUDIO_PLAYBACK_WITH_HAPTICS:
        case USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION:
        case USECASE_AUDIO_PLAYBACK_PHONE:
            return LOW_LATENCY_PLATFORM_DELAY;
            delay = LOW_LATENCY_PLATFORM_DELAY;
            break;
        case USECASE_AUDIO_PLAYBACK_OFFLOAD:
        case USECASE_AUDIO_PLAYBACK_OFFLOAD2:
             return PCM_OFFLOAD_PLATFORM_DELAY;
            delay = PCM_OFFLOAD_PLATFORM_DELAY;
            break;
        case USECASE_AUDIO_PLAYBACK_ULL:
             return ULL_PLATFORM_DELAY;
            delay = ULL_PLATFORM_DELAY;
            break;
        case USECASE_AUDIO_PLAYBACK_MMAP:
             return MMAP_PLATFORM_DELAY;
            delay = MMAP_PLATFORM_DELAY;
            break;
        default:
            return 0;
            break;
    }

    uc_info = get_usecase_from_list(adev, usecase);

    if (uc_info != NULL) {
        if (uc_info->type == PCM_PLAYBACK)
            delay += platform_get_snd_device_delay(uc_info->out_snd_device);
        else
            ALOGE("%s: Invalid uc_info->type %d", __func__, uc_info->type);
    }

    return delay;
}

int64_t platform_capture_latency(struct audio_device *adev, audio_usecase_t usecase)
{
    int64_t delay = 0LL;
    struct audio_usecase *uc_info;

    uc_info = get_usecase_from_list(adev, usecase);

    if (uc_info != NULL) {
        if (uc_info->type == PCM_CAPTURE)
            delay += platform_get_snd_device_delay(uc_info->in_snd_device);
        else
            ALOGE("%s: Invalid uc_info->type %d", __func__, uc_info->type);
    }

    return delay;
}

int platform_update_usecase_from_source(int source, int usecase)
Loading