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
diff --git a/hal/audio_extn/hw_loopback.c b/hal/audio_extn/hw_loopback.c
index 5b67284..6da9313 100644
--- a/hal/audio_extn/hw_loopback.c
+++ b/hal/audio_extn/hw_loopback.c
@@ -143,11 +143,21 @@
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;
@@ -178,30 +188,31 @@
}
if (loopback_patch->loopback_sink.role == AUDIO_PORT_ROLE_SINK) {
switch (loopback_patch->loopback_sink.type) {
- 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)) {
- 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;
- break;
- default:
- break;
+ case AUDIO_PORT_TYPE_DEVICE :
+ if ((loopback_patch->loopback_sink.config_mask &
+ AUDIO_PORT_CONFIG_FORMAT) &&
+ (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_supported = true;
+ break;
+ default:
+ break;
}
- }
- break;
- default :
- break;
- //Unsupported as of now, need to extend for other sink types
+ } else {
+ ALOGE("%s, Unsupported sink port device %d", __func__,loopback_patch->loopback_sink.ext.device.type);
+ }
+ break;
+ default :
+ break;
+ //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 @@
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 @@
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 @@
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
diff --git a/qahw_api/test/trans_loopback_test.c b/qahw_api/test/trans_loopback_test.c
index 0fc2f08..a0673de 100644
--- a/qahw_api/test/trans_loopback_test.c
+++ b/qahw_api/test/trans_loopback_test.c
@@ -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 @@
#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 @@
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;
-
- 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]);
- 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;
+ 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,"\nTranscode loopback test begin\n");
+ if (play_duration_in_seconds < 0 | play_duration_in_seconds > 3600) {
+ fprintf(log_file,
+ "\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;
+
/* 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 @@
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 @@
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");
+ }