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

Commit d1f56eb8 authored by Siddartha Shaik's avatar Siddartha Shaik Committed by Shiv Maliyappanahalli
Browse files

audio: hal: support line out for transcode loopback

HW loopback extension and test app update
to support line out for transcode loopback.

CRs-Fixed: 2077703
Change-Id: I415830e3faefd7873c80075de8bf745780e7d0fb
parent 5857aebf
Loading
Loading
Loading
Loading
+37 −22
Original line number Diff line number Diff line
@@ -143,11 +143,21 @@ int init_patch_database(patch_db_t* patch_db)
    return patch_init_rc;
}

bool is_supported_sink_device(audio_devices_t sink_device_mask)
{
    if((sink_device_mask & AUDIO_DEVICE_OUT_SPEAKER) ||
       (sink_device_mask & AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
       (sink_device_mask & AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
           return true;
       }
    return false;
}

/* Get patch type based on source and sink ports configuration */
/* Only ports of type 'DEVICE' are supported */
patch_handle_type_t get_loopback_patch_type(loopback_patch_t*  loopback_patch)
{
    bool is_source_hdmi=false, is_sink_spkr=false;
    bool is_source_hdmi=false, is_sink_supported=false;
    if (loopback_patch->patch_handle_id != PATCH_HANDLE_INVALID) {
        ALOGE("%s, Patch handle already exists", __func__);
        return loopback_patch->patch_handle_id;
@@ -181,19 +191,20 @@ patch_handle_type_t get_loopback_patch_type(loopback_patch_t* loopback_patch)
        case AUDIO_PORT_TYPE_DEVICE :
            if ((loopback_patch->loopback_sink.config_mask &
                AUDIO_PORT_CONFIG_FORMAT) &&
                    (loopback_patch->loopback_sink.ext.device.type &
                     AUDIO_DEVICE_OUT_SPEAKER)) {
                (is_supported_sink_device(loopback_patch->loopback_sink.ext.device.type))) {
                    switch (loopback_patch->loopback_sink.format) {
                    case AUDIO_FORMAT_PCM:
                    case AUDIO_FORMAT_PCM_16_BIT:
                    case AUDIO_FORMAT_PCM_32_BIT:
                    case AUDIO_FORMAT_PCM_8_24_BIT:
                    case AUDIO_FORMAT_PCM_24_BIT_PACKED:
                              is_sink_spkr = true;
                        is_sink_supported = true;
                        break;
                    default:
                        break;
                    }
            } else {
                ALOGE("%s, Unsupported sink port device %d", __func__,loopback_patch->loopback_sink.ext.device.type);
            }
            break;
        default :
@@ -201,7 +212,7 @@ patch_handle_type_t get_loopback_patch_type(loopback_patch_t* loopback_patch)
            //Unsupported as of now, need to extend for other sink types
        }
    }
    if (is_source_hdmi && is_sink_spkr) {
    if (is_source_hdmi && is_sink_supported) {
        return AUDIO_PATCH_HDMI_IN_SPKR_OUT;
    }
    ALOGE("%s, Unsupported source or sink port config", __func__);
@@ -403,6 +414,7 @@ int create_loopback_session(loopback_patch_t *active_loopback_patch)
        active_loopback_patch->source_stream)) {
        ALOGE("%s: %s", __func__, compress_get_error(active_loopback_patch->
        source_stream));
        active_loopback_patch->source_stream = NULL;
        ret = -EIO;
        goto exit;
    } else if (active_loopback_patch->source_stream == NULL) {
@@ -429,6 +441,7 @@ int create_loopback_session(loopback_patch_t *active_loopback_patch)
        active_loopback_patch->sink_stream)) {
        ALOGE("%s: %s", __func__, compress_get_error(active_loopback_patch->
                sink_stream));
        active_loopback_patch->sink_stream = NULL;
        ret = -EIO;
        goto exit;
    } else if (active_loopback_patch->sink_stream == NULL) {
@@ -525,6 +538,8 @@ int audio_extn_hw_loopback_create_audio_patch(struct audio_hw_device *dev,
                                audio_loopback_mod->patch_db.num_patches]);
    active_loopback_patch->patch_handle_id = PATCH_HANDLE_INVALID;
    active_loopback_patch->patch_state = PATCH_INACTIVE;
    active_loopback_patch->patch_stream.ip_hdlr_handle = NULL;
    active_loopback_patch->patch_stream.adsp_hdlr_stream_handle = NULL;
    memcpy(&active_loopback_patch->loopback_source, &sources[0], sizeof(struct
    audio_port_config));
    memcpy(&active_loopback_patch->loopback_sink, &sinks[0], sizeof(struct
+85 −18
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
/*#define LOG_NDEBUG 0*/
#include <fcntl.h>
#include <linux/netlink.h>
#include <getopt.h>
#include <pthread.h>
#include <poll.h>
#include <stdlib.h>
@@ -91,10 +92,16 @@ const char *log_filename = NULL;
#define TRANSCODE_LOOPBACK_SOURCE_PORT_ID 0x4C00
#define TRANSCODE_LOOPBACK_SINK_PORT_ID 0x4D00

#define DEVICE_SOURCE 0
#define DEVICE_SINK 1

#define MAX_MODULE_NAME_LENGTH  100

#define DEV_NODE_CHECK(node_name,node_id) strncmp(node_name,node_id,strlen(node_name))

/* Function declarations */
void usage();

typedef enum source_port_type {
    SOURCE_PORT_NONE,
    SOURCE_PORT_HDMI,
@@ -502,30 +509,86 @@ void process_loopback_data(void *ptr)
    pthread_exit(0);
}

bool is_device_supported(uint32_t device_id)
{
    switch(device_id)
    {
        case AUDIO_DEVICE_OUT_SPEAKER :
        case AUDIO_DEVICE_OUT_WIRED_HEADSET :
        case AUDIO_DEVICE_OUT_WIRED_HEADPHONE :
            return true;
        default :
            return false;
    }
}

void set_device(uint32_t device_type, uint32_t device_id)
{
    transcode_loopback_config_t *transcode_loopback_config = &g_trnscode_loopback_config;
    device_id = is_device_supported(device_id) ? device_id : AUDIO_DEVICE_OUT_SPEAKER;
    switch( device_type )
    {
        case DEVICE_SINK:
            transcode_loopback_config->sink_config.ext.device.type = device_id;
        break;
        case DEVICE_SOURCE:
            transcode_loopback_config->source_config.ext.device.type = device_id;
        break;
    }
}

int main(int argc, char *argv[]) {

    int status = 0;
    uint32_t play_duration_in_seconds = 30,play_duration_elapsed_msec = 0,play_duration_in_msec = 0;
    uint32_t play_duration_in_seconds = 600,play_duration_elapsed_msec = 0,play_duration_in_msec = 0, sink_device = 2;
    source_port_type_t source_port_type = SOURCE_PORT_NONE;
    log_file = stdout;
    transcode_loopback_config_t    *transcode_loopback_config = NULL;
    transcode_loopback_config_t *temp = NULL;

    struct option long_options[] = {
        /* These options set a flag. */
        {"sink-device", required_argument,    0, 'd'},
        {"play-duration",  required_argument,    0, 'p'},
        {"help",          no_argument,          0, 'h'},
        {0, 0, 0, 0}
    };

    int opt = 0;
    int option_index = 0;

    while ((opt = getopt_long(argc,
                              argv,
                              "-d:p:h",
                              long_options,
                              &option_index)) != -1) {

        fprintf(log_file, "for argument %c, value is %s\n", opt, optarg);

        switch (opt) {
        case 'd':
            sink_device = atoi(optarg);
            break;
        case 'p':
            play_duration_in_seconds = atoi(optarg);
            break;
        case 'h':
        default :
            usage();
            return 0;
            break;
        }
    }

    fprintf(log_file,"\nUsage : trans_loopback_test <optional : duration_in_seconds>\n");
    fprintf(log_file,"\nTranscode loopback test begin\n");
    play_duration_in_seconds = 600;
    if (argc == 2) {
        play_duration_in_seconds = atoi(argv[1]);
    if (play_duration_in_seconds < 0 | play_duration_in_seconds > 3600) {
            fprintf(log_file,
                    "\nPlayback duration %s invalid or unsupported(range : 1 to 3600, defaulting to 600 seconds )\n",
                    argv[1]);
                    "\nPlayback duration %d invalid or unsupported(range : 1 to 3600, defaulting to 600 seconds )\n",
                    play_duration_in_seconds);
            play_duration_in_seconds = 600;
    }
    }
    play_duration_in_msec = play_duration_in_seconds * 1000;

    transcode_loopback_config_t    *transcode_loopback_config = NULL;
    transcode_loopback_config_t *temp = NULL;

    /* Register the SIGINT to close the App properly */
    if (signal(SIGINT, break_signal_handler) == SIG_ERR) {
        fprintf(log_file, "Failed to register SIGINT:%d\n",errno);
@@ -536,6 +599,9 @@ int main(int argc, char *argv[]) {
    init_transcode_loopback_config(&temp);
    transcode_loopback_config = &g_trnscode_loopback_config;

    /* Set devices */
    set_device(DEVICE_SINK,sink_device);

    /* Load HAL */
    fprintf(log_file,"\nLoading HAL for loopback usecase begin\n");
    primary_hal_handle = load_hal(transcode_loopback_config->devices);
@@ -581,11 +647,12 @@ exit_transcode_loopback_test:

    fprintf(log_file,"\nTranscode loopback test end\n");
    return 0;
usage:
    fprintf(log_file,"\nInvald arguments\n");
    fprintf(log_file,"\nUsage : trans_loopback_test <duration_in_seconds>\n");
    fprintf(log_file,"\nExample to play for 1 minute : trans_loopback_test 60\n");
    return 0;
}

void usage()
{
    fprintf(log_file,"\nUsage : trans_loopback_test -p <duration_in_seconds> -d <sink_device_id>\n");
    fprintf(log_file,"\nExample to play for 1 minute on speaker device: trans_loopback_test -p 60 -d 2\n");
    fprintf(log_file,"\nExample to play for 5 minutes on headphone device: trans_loopback_test -p 300 -d 8\n");
    fprintf(log_file,"\nHelp : trans_loopback_test -h\n");
 }