blob: b3da21abae54d022062234edbe287f27dd74f57a [file] [log] [blame]
/*
* Copyright (c) 2016-2017,2019 The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright (C) 2015 The Android Open Source Project *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Test app extension to exercise QAP (Non-tunnel Decode) */
#include <ctype.h>
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <cutils/properties.h>
#include <cutils/list.h>
#include <cutils/str_parms.h>
#include <log/log.h>
#include <system/audio.h>
#include <qap_api.h>
#include <qti_audio.h>
#include "qahw_playback_test.h"
#include <dolby_ms12.h>
#undef LOG_TAG
#define LOG_TAG "HAL_TEST"
#undef LOG_NDEBUG
/*#define LOG_NDEBUG 0*/
#if LINUX_ENABLED
#if defined(__LP64__)
#define QAC_LIB_MS12 "/usr/lib64/libdolby_ms12_wrapper.so"
#else
#define QAC_LIB_MS12 "/usr/lib/libdolby_ms12_wrapper.so"
#endif
#define QAC_LIB_M8 "libdts_m8_wrapper.so"
#else
#define QAC_LIB_MS12 "/system/lib/libdolby_ms12_wrapper.so"
#define QAC_LIB_M8 "/system/lib/libdts_m8_wrapper.so"
#endif
#define SESSION_BLURAY 1
#define SESSION_BROADCAST 2
#define MAX_OUTPUT_CHANNELS 8
#define FRAME_SIZE 32768 /* 32k size */
#define MAX_BUFFER_SIZE 32768 /* 32k size */
#define CONTIGUOUS_TIMESTAMP 0x7fffffff
#define TIMESTAMP_ARRAY_SIZE 2048
#define DOLBY 1
#define DTS 2
#define FRAME_SIZE_FOR_2CH_PCM 6144 /* For 48k samplerate, 2 ch, 2 bytes */
#define PCM_16_BITWIDTH 16
#define PCM_24_BITWIDTH 24
#define DEFAULT_SAMPLE_RATE 48000
#define MAX_QAP_MODULE_OUT 3
extern bool stop_playback;
bool is_media_fmt_changed[MAX_QAP_MODULE_OUT];
int new_output_conf_index = 0;
qap_lib_handle_t ms12_lib_handle = NULL;
qap_lib_handle_t m8_lib_handle = NULL;
qap_session_handle_t qap_session_handle = NULL;
qahw_module_handle_t *qap_out_hal_handle = NULL;
qahw_module_handle_t *qap_out_spk_handle = NULL;
qahw_module_handle_t *qap_out_hdmi_handle = NULL;
qahw_module_handle_t *qap_out_hp_handle = NULL;
audio_io_handle_t qap_stream_out_spk_handle = 0x999;
audio_io_handle_t qap_stream_out_hdmi_handle = 0x998;
audio_io_handle_t qap_stream_out_hp_handle = 0x997;
audio_io_handle_t qap_stream_out_cmpr_handle = 0x996;
FILE *fp_output_writer_spk = NULL;
FILE *fp_output_writer_hp = NULL;
FILE *fp_output_writer_hdmi = NULL;
FILE *fp_output_timestamp_file = NULL;
FILE *fp_ecref = NULL;
unsigned char data_buf[MAX_BUFFER_SIZE];
uint32_t output_device_id = 0;
uint16_t input_streams_count = 0;
bool hdmi_connected = false;
bool play_through_bt = false;
bool encode = false;
bool dolby_formats = false;
bool timestamp_mode = false;
int data_write_count = 0;
int data_callback_count = 0;
bool play_list = false;
int play_list_cnt = 0;
uint8_t session_type = SESSION_BLURAY;
pthread_t main_input_thread;
pthread_attr_t main_input_thrd_attr;
pthread_cond_t main_eos_cond;
pthread_mutex_t main_eos_lock;
pthread_cond_t sec_eos_cond;
pthread_mutex_t sec_eos_lock;
pthread_cond_t main2_eos_cond;
pthread_mutex_t main2_eos_lock;
bool main_eos_received = false;
bool main2_eos_received = false;
bool sec_eos_received = false;
dlb_ms12_session_param_t dlb_param;
dlb_ms12_session_param_t dlb_param_hp;
qap_session_outputs_config_t session_output_config;
bool session_output_configured = false;
struct timeval tcold_start, tcold_stop;
struct timeval tcont_ts1, tcont_ts2;
double cold_start, cold_stop;
long int data_callback_ts_arr[TIMESTAMP_ARRAY_SIZE];
long int data_input_ts_arr[TIMESTAMP_ARRAY_SIZE];
double data_input_st_arr[TIMESTAMP_ARRAY_SIZE];
double data_callback_st_arr[TIMESTAMP_ARRAY_SIZE];
bool has_system_input = false;
char session_kv_pairs[256];
bool primary_stream_close = false;
int8_t stream_cnt = 0;
uint32_t dsp_latency = 0;
static int get_qap_session_out_config_index_for_id(uint32_t out_id)
{
int index = -1, i;
for (i = 0; i < MAX_QAP_MODULE_OUT; i++)
if (session_output_config.output_config[i].id == out_id)
index = i;
return index;
}
static void set_qahw_stream_channel_map(qahw_stream_handle_t *out_handle, qap_output_config_t *qap_config)
{
struct qahw_out_channel_map_param chmap_param = {0};
int i = 0;
if (qap_config == NULL || out_handle == NULL) {
return;
}
chmap_param.channels = qap_config->channels;
for (i = 0; i < chmap_param.channels && i < AUDIO_CHANNEL_COUNT_MAX && i < QAP_AUDIO_MAX_CHANNELS;
i++) {
chmap_param.channel_map[i] = qap_config->ch_map[i];
}
qahw_out_set_param_data(out_handle, QAHW_PARAM_OUT_CHANNEL_MAP, (qahw_param_payload *) &chmap_param);
}
static void update_combo_dev_kvpairs()
{
bool enable_spk = false;
bool enable_hp = false;
bool enable_hdmi = false;
bool combo_enabled = false;
char dev_kv_pair[16] = {0};
ALOGV("%s:%d output device id %d", __func__, __LINE__, output_device_id);
if (output_device_id & AUDIO_DEVICE_OUT_HDMI)
enable_hdmi = true;
if (output_device_id & AUDIO_DEVICE_OUT_WIRED_HEADPHONE)
enable_hp = true;
if (output_device_id & AUDIO_DEVICE_OUT_SPEAKER)
enable_spk = true;
// Update the kv_pair based on the output device selsction
// To select hdmi, spekaer and headphone: o_device=1,2,8
// To select hdmi, headphone: o_device=2,8
// To select hdmi, spekaer : o_device=1,8
// To select spekaer and headphone: o_device=1,2
if (enable_hdmi && enable_hp && enable_spk) {
sprintf(dev_kv_pair, "o_device=1,2,8");
combo_enabled = true;
} else if (enable_hdmi && enable_hp) {
sprintf(dev_kv_pair, "o_device=2,8");
combo_enabled = true;
} else if (enable_hdmi && enable_spk) {
sprintf(dev_kv_pair, "o_device=1,8");
combo_enabled = true;
} else if (enable_hp && enable_spk) {
sprintf(dev_kv_pair, "o_device=1,2");
combo_enabled = true;
}
if (combo_enabled)
strcat(session_kv_pairs, dev_kv_pair);
ALOGV("%s:%d session set param %s and combo_enabled %d", __func__, __LINE__, session_kv_pairs, combo_enabled);
return;
}
static void update_session_outputs_config(int hdmi_render_format, int in_channels, int bitwidth, int smpl_rate)
{
bool enable_spk = false;
bool enable_hp = false;
bool enable_hdmi = false;
bool combo_enabled = false;
char dev_kv_pair[16] = {0};
bool enable_ecref = false;
ALOGV("%s:%d output device id %d render format = %d", __func__, __LINE__, output_device_id, hdmi_render_format);
if (output_device_id & AUDIO_DEVICE_OUT_HDMI)
enable_hdmi = true;
if (output_device_id & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
output_device_id & AUDIO_DEVICE_OUT_LINE)
enable_hp = true;
if (output_device_id & AUDIO_DEVICE_OUT_SPEAKER)
enable_spk = true;
if (ec_ref)
enable_ecref = true;
if (enable_hdmi) {
session_output_config.output_config[session_output_config.num_output].id = AUDIO_DEVICE_OUT_HDMI;
if (hdmi_render_format == 1) {
session_output_config.output_config[session_output_config.num_output].id = AUDIO_DEVICE_OUT_HDMI|AUDIO_FORMAT_AC3;
session_output_config.output_config[session_output_config.num_output].format = QAP_AUDIO_FORMAT_AC3;
} else if (hdmi_render_format == 2) {
session_output_config.output_config[session_output_config.num_output].id = AUDIO_DEVICE_OUT_HDMI|AUDIO_FORMAT_E_AC3;
session_output_config.output_config[session_output_config.num_output].format = QAP_AUDIO_FORMAT_EAC3;
} else if (hdmi_render_format == 3) {
session_output_config.output_config[session_output_config.num_output].id = AUDIO_DEVICE_OUT_HDMI|AUDIO_FORMAT_DTS;
session_output_config.output_config[session_output_config.num_output].format = QAP_AUDIO_FORMAT_DTS;
} else {
if (bitwidth == PCM_24_BITWIDTH) {
session_output_config.output_config[session_output_config.num_output].format = QAP_AUDIO_FORMAT_PCM_24_BIT_PACKED;
session_output_config.output_config[session_output_config.num_output].bit_width = PCM_24_BITWIDTH;
} else {
session_output_config.output_config[session_output_config.num_output].format = QAP_AUDIO_FORMAT_PCM_16_BIT;
session_output_config.output_config[session_output_config.num_output].bit_width = PCM_16_BITWIDTH;
}
}
session_output_config.output_config[session_output_config.num_output].channels = in_channels;
session_output_config.output_config[session_output_config.num_output].sample_rate = smpl_rate;
session_output_config.num_output++;
}
if (enable_hp) {
session_output_config.output_config[session_output_config.num_output].id = AUDIO_DEVICE_OUT_LINE;
session_output_config.output_config[session_output_config.num_output].channels = popcount(AUDIO_CHANNEL_OUT_STEREO);
session_output_config.output_config[session_output_config.num_output].sample_rate = smpl_rate;
if (bitwidth == PCM_24_BITWIDTH) {
session_output_config.output_config[session_output_config.num_output].format = QAP_AUDIO_FORMAT_PCM_24_BIT_PACKED;
session_output_config.output_config[session_output_config.num_output].bit_width = PCM_24_BITWIDTH;
} else {
session_output_config.output_config[session_output_config.num_output].format = QAP_AUDIO_FORMAT_PCM_16_BIT;
session_output_config.output_config[session_output_config.num_output].bit_width = PCM_16_BITWIDTH;
}
session_output_config.num_output++;
}
if (enable_spk) {
session_output_config.output_config[session_output_config.num_output].channels = popcount(AUDIO_CHANNEL_OUT_STEREO);
session_output_config.output_config[session_output_config.num_output].id = AUDIO_DEVICE_OUT_SPEAKER;
session_output_config.output_config[session_output_config.num_output].sample_rate = smpl_rate;
if (bitwidth == PCM_24_BITWIDTH) {
session_output_config.output_config[session_output_config.num_output].format = QAP_AUDIO_FORMAT_PCM_24_BIT_PACKED;
session_output_config.output_config[session_output_config.num_output].bit_width = PCM_24_BITWIDTH;
} else {
session_output_config.output_config[session_output_config.num_output].format = QAP_AUDIO_FORMAT_PCM_16_BIT;
session_output_config.output_config[session_output_config.num_output].bit_width = PCM_16_BITWIDTH;
}
session_output_config.num_output++;
}
if (enable_ecref) {
session_output_config.output_config[session_output_config.num_output].channels = popcount(AUDIO_CHANNEL_OUT_STEREO);
session_output_config.output_config[session_output_config.num_output].id = AUDIO_DEVICE_OUT_PROXY;
session_output_config.output_config[session_output_config.num_output].sample_rate = smpl_rate;
if (bitwidth == PCM_24_BITWIDTH) {
session_output_config.output_config[session_output_config.num_output].format = QAP_AUDIO_FORMAT_PCM_24_BIT_PACKED;
session_output_config.output_config[session_output_config.num_output].bit_width = PCM_24_BITWIDTH;
} else {
session_output_config.output_config[session_output_config.num_output].format = QAP_AUDIO_FORMAT_PCM_16_BIT;
session_output_config.output_config[session_output_config.num_output].bit_width = PCM_16_BITWIDTH;
}
session_output_config.num_output++;
}
ALOGV("%s:%d num_output = %d", __func__, __LINE__, session_output_config.num_output);
return;
}
static void update_kvpairs_for_encode(int out_device_id) {
uint8_t device_id;
char command[64];
if (out_device_id == AUDIO_DEVICE_OUT_HDMI)
device_id = 8;
switch (render_format) {
case 1:
sprintf(command, "o_device=%d;od=;", device_id);
strcat(session_kv_pairs, command);
encode = true;
break;
case 2:
sprintf(command, "o_device=%d;odp=;", device_id);
strcat(session_kv_pairs, command);
encode = true;
break;
case 3:
sprintf(command, "o_device=%d;render_format=odts;enabletransencode;", device_id);
strcat(session_kv_pairs, command);
encode = true;
break;
default:
encode = false;
break;
}
ALOGV("%s::%d output device %d and session set params %s", __func__, __LINE__, out_device_id, session_kv_pairs);
return;
}
static void qap_wrapper_create_multi_channel_dump(char *path) {
fp_output_writer_hdmi = fopen(path,"wb");
if (fp_output_writer_hdmi)
fprintf(stdout, "output file ::%s has been generated.\n", path);
else
fprintf(stderr, "Failed open hdmi dump file\n");
}
/*
* cold_time_latency is the time difference between the session open
* and the first data output received from decoder.
*
* cont_time_latency is the avg time taken to decode the input buffers
* i.e. avg of the time differences between the time the input buffer feeded
* and the time the o/p buffer received
*/
static void qap_wrapper_measure_kpi_values(double cold_start, double cold_stop)
{
int i=0, m=0, j=0;
int cnt = 0;
double syst_time_arr[TIMESTAMP_ARRAY_SIZE];
double total_lat = 0;
double cold_time_latency, cont_time_latency;
cold_time_latency = cold_stop - cold_start;
memset(syst_time_arr,0, sizeof(syst_time_arr));
if (data_write_count > TIMESTAMP_ARRAY_SIZE)
data_write_count = TIMESTAMP_ARRAY_SIZE;
if (data_callback_count > TIMESTAMP_ARRAY_SIZE)
data_callback_count = TIMESTAMP_ARRAY_SIZE;
for (i = 6; i < data_write_count; i++) {
for(j = 6; j < ((data_callback_count < TIMESTAMP_ARRAY_SIZE) ? data_callback_count : TIMESTAMP_ARRAY_SIZE); j++) {
if( abs(data_input_ts_arr[i] - data_callback_ts_arr[j]) <= 4000) {
syst_time_arr[cnt++] = (data_callback_st_arr[j] - data_input_st_arr[i]);
}
}
}
for(m = 0; m < cnt; m++) {
total_lat += syst_time_arr[m];
ALOGV("%d system time diff %lf", __LINE__, syst_time_arr[m]);
}
cont_time_latency = total_lat/(cnt);
fprintf(stdout, "cold time latency %lf ms, avg cont time latency %lf ms,"
"total cont time latency %f ms, total count %d\n",
cold_time_latency, cont_time_latency, total_lat, cnt);
if (dsp_latency)
fprintf(stdout, "Dsp latency = %lu ms \n", dsp_latency);
}
static void qap_wrapper_read_frame_size_from_file(qap_audio_buffer_t *buffer, FILE *fp_framesize)
{
if (NULL != fp_framesize) {
char tempstr[100];
fgets(tempstr, sizeof(tempstr), fp_framesize);
buffer->common_params.size = atoi(tempstr);
}
}
static void read_bytes_timestamps_from_file(qap_audio_buffer_t *buffer, FILE *fp_timestamp, FILE *fp_input_file)
{
if (NULL != fp_timestamp) {
char tempstr[100] = {0};
int seek_offset = 0;
fgets(tempstr, sizeof(tempstr), fp_timestamp);
printf("%s and tempstr is %s \n", __FUNCTION__, tempstr);
char * token = strtok(tempstr, ",");
if (token != NULL) {
buffer->common_params.size = atoi(token);
if(token!= NULL) {
token = strtok(NULL, ",");
if (token!= NULL) {
buffer->common_params.timestamp = atoi(token);
ALOGV("%s and timestamp to be pushed to queue is %lld", __FUNCTION__, buffer->common_params.timestamp);
}
token = strtok(NULL, ",");
if (token != NULL) {
seek_offset = atoi(token);
if (fp_input_file && seek_offset > 0)
fseek(fp_input_file, seek_offset, SEEK_CUR);
}
}
} else {
buffer->common_params.timestamp = CONTIGUOUS_TIMESTAMP;
buffer->common_params.size = 0;
}
}
}
bool is_qap_session_active(int argc, char* argv[], char *kvp_string) {
char *qap_kvp = NULL;
char *cmd_str = NULL;
char *tmp_str = NULL;
int status = 0;
cmd_str = (char *)qap_wrapper_get_cmd_string_from_arg_array(argc, argv, &status);
if (status > 0) {
qap_kvp = qap_wrapper_get_single_kvp("qap", cmd_str, &status);
if (qap_kvp == NULL) {
return false;
}
strncpy(kvp_string, cmd_str, strlen(cmd_str));
if (cmd_str != NULL) {
free(cmd_str);
cmd_str = NULL;
}
}
return true;
}
char* check_for_playlist(char *kvp_string) {
char *file_str = NULL;
char *tmp_str = NULL;
char *play_list = NULL;
int len = 0;
tmp_str = strstr(kvp_string, "g=/");
if (tmp_str != NULL) {
file_str = strstr(kvp_string, ".txt");
len = file_str - tmp_str;
play_list = (char*) calloc(1, sizeof(char) * (len+4));
strncpy(play_list, tmp_str+2, len+2);
}
return play_list;
}
int start_playback_through_qap_playlist(char *cmd_kvp_str[], int num_of_streams, char *kvp_string, stream_config stream_param[],
bool qap_wrapper_session_active, qahw_module_handle_t *hal_handle) {
stream_config *stream = NULL;
int rc = 0;
bool broad_cast = false, bd = false;
int i = 0, curr_clip_type = DOLBY, prev_clip_type;
if (strstr(kvp_string, "broadcast"))
broad_cast = true;
else if(strstr(kvp_string, "bd"))
bd = true;
do {
fprintf(stdout, "cmd_kvp_string is %s kvp_string %s and num_of_streams %d\n", cmd_kvp_str[i], kvp_string, num_of_streams);
stream = &stream_param[i];
fprintf(stdout, "stream->filename is %s\n", stream->filename);
if (stream->filename) {
prev_clip_type = curr_clip_type;
if ((stream->file_stream = fopen(stream->filename, "r"))== NULL) {
fprintf(stderr, "Cannot open audio file %s\n", stream->filename);
return -EINVAL;
}
if (strstr(stream->filename, ".dts")) {
curr_clip_type = DTS;
} else {
curr_clip_type = DOLBY;
}
}
get_file_format(stream);
fprintf(stdout, "Playing from:%s\n", stream->filename);
qap_module_handle_t qap_module_handle = NULL;
if ((bd || (prev_clip_type != curr_clip_type)) && qap_wrapper_session_active) {
fprintf(stdout, " prev_clip_type is %d curr_clip_type is %d\n", prev_clip_type, curr_clip_type);
qap_wrapper_session_close();
qap_wrapper_session_active = false;
}
if (!qap_wrapper_session_active) {
if (broad_cast) {
cmd_kvp_str[i] = realloc(cmd_kvp_str[i], strlen(cmd_kvp_str[i])+11);
strcat(strcat(cmd_kvp_str[i], ";"), "broadcast");
} else if (bd) {
cmd_kvp_str[i] = realloc(cmd_kvp_str[i], strlen(cmd_kvp_str[i])+4);
strcat(strcat(cmd_kvp_str[i], ";"), "bd");
}
rc = qap_wrapper_session_open(cmd_kvp_str[i], stream, num_of_streams, hal_handle);
if (rc != 0) {
fprintf(stderr, "Session Open failed\n");
return -EINVAL;
}
qap_wrapper_session_active = true;
}
if (qap_wrapper_session_active) {
stream->qap_module_handle = qap_wrapper_stream_open(stream);
if (stream->qap_module_handle == NULL) {
fprintf(stderr, "QAP Stream open Failed\n");
} else {
fprintf(stdout, "QAP module handle is %p and file name is %s\n", stream->qap_module_handle, stream->filename);
qap_wrapper_start_stream(&stream_param[i]);
free(stream->filename);
stream->filename = NULL;
free(cmd_kvp_str[i]);
cmd_kvp_str[i] = NULL;
}
}
i++;
while (!primary_stream_close) {
usleep(50000);
fprintf(stderr, "QAP Stream not closed\n");
}
fprintf(stderr, "QAP Stream closed\n");
} while (i <num_of_streams);
if (qap_wrapper_session_active) {
qap_wrapper_session_close();
qap_wrapper_session_active = false;
}
return 0;
}
#ifdef QAP
char *qap_wrapper_get_single_kvp(const char *key, const char *kv_pairs, int *status)
{
char *kvp = NULL;
char *tempstr = NULL;
char *token = NULL;
char *context1 = NULL;
char *context2 = NULL;
char *temp_kvp = NULL;
char *temp_key = NULL;
if (NULL == key || NULL == kv_pairs) {
*status = -EINVAL;
return NULL;
}
tempstr = strdup(kv_pairs);
token = strtok_r(tempstr, ";", &context1);
if (token != NULL) {
temp_kvp = strdup(token);
if (temp_kvp != NULL) {
temp_key = strtok_r(temp_kvp, "=", &context2);
if (!strncmp(key, temp_key, strlen(key))) {
kvp = calloc(1, (strlen(token) + 1) * sizeof(char));
strncat(kvp, token, strlen(token));
return kvp;
}
free(temp_kvp);
}
while (token != NULL) {
token = strtok_r(NULL, ";", &context1);
if (token != NULL) {
temp_kvp = strdup(token);
if (temp_kvp != NULL) {
temp_key = strtok_r(temp_kvp, "=", &context2);
if (!strncmp(key, temp_key, strlen(key))) {
kvp = calloc(1, (strlen(token) + 1) * sizeof(char));
strncat(kvp, token, strlen(token));
return kvp;
}
free(temp_kvp);
temp_kvp = NULL;
}
}
}
free(tempstr);
}
return NULL;
}
#endif
int *qap_wrapper_get_int_value_array(const char *kvp, int *count, int *status __unused)
{
char *tempstr1;
char *tempstr2;
char *l1;
char *l2 __unused;
char *ctx1;
char *ctx2 __unused;
int *val = NULL;
int i = 0;
char *s;
char *endstr;
int temp = 0;
char *jump;
*count = 0;
if (kvp == NULL) {
return NULL;
}
tempstr1 = strdup(kvp);
l1 = strtok_r(tempstr1, "=", &ctx1);
if (l1 != NULL) {
/* jump from key to value */
l1 = strtok_r(NULL, "=", &ctx1);
if (l1 != NULL) {
tempstr2 = strdup(l1);
s = tempstr2;
for (i=0; s[i]; s[i]==',' ? i++ : *s++);
temp = i;
val = calloc(1, (i + 1)*sizeof(int));
i = 0;
val[i++] = strtol(tempstr2, &endstr, 0);
while (i <= temp) {
jump = endstr + 1;
val[i++] = strtol(jump, &endstr, 0);
}
free(tempstr2);
}
}
free(tempstr1);
*count = i;
return val;
}
char * qap_wrapper_get_cmd_string_from_arg_array(int argc, char * argv[], int *status)
{
char * kvps;
int idx;
int has_key = 0;
int mem = 0;
fprintf(stdout, "%s %d in", __func__, __LINE__);
if (argc < 2 || NULL == argv) {
fprintf(stdout, "%s %d returning EINVAL\n", __func__, __LINE__);
*status = -EINVAL;
return NULL;
}
for (idx = 0; idx < argc; idx++) {
mem += (strlen(argv[idx]) + 2); /* Extra byte to insert delim ';' */
}
if (mem > 0)
kvps = calloc(1, mem * sizeof(char));
else {
*status = -EINVAL;
fprintf(stdout, "%s %d returning EINVAL\n", __func__, __LINE__);
return NULL;
}
if (NULL == kvps) {
*status = -ENOMEM;
fprintf(stdout, "%s %d returning EINVAL\n", __func__, __LINE__);
return NULL;
}
for (idx = 1; idx < argc; idx++) {
if (( argv[idx][0] == '-') &&
(argv[idx][1] < '0' || argv[idx][1] > '9')) {
if (has_key) {
strcat(kvps, ";");
has_key = 0;
}
strcat(kvps, argv[idx]+1);
strcat(kvps, "=");
has_key = 1;
} else if (has_key) {
strcat(kvps, argv[idx]);
strcat(kvps, ";");
has_key = 0;
} else {
*status = -EINVAL;
if (kvps != NULL) {
free(kvps);
kvps = NULL;
}
fprintf(stdout, "%s %d returning EINVAL\n", __func__, __LINE__);
return NULL;
}
}
*status = mem;
fprintf(stdout, "%s %d returning\n", __func__, __LINE__);
return kvps;
}
static int qap_wrapper_map_input_format(audio_format_t audio_format, qap_audio_format_t *format)
{
if (audio_format == AUDIO_FORMAT_AC3) {
*format = QAP_AUDIO_FORMAT_AC3;
fprintf(stdout, "File Format is AC3!\n");
} else if (audio_format == AUDIO_FORMAT_E_AC3) {
*format = QAP_AUDIO_FORMAT_EAC3;
fprintf(stdout, "File Format is E_AC3!\n");
} else if ((audio_format == AUDIO_FORMAT_AAC_ADTS_LC) ||
(audio_format == AUDIO_FORMAT_AAC_ADTS_HE_V1) ||
(audio_format == AUDIO_FORMAT_AAC_ADTS_HE_V2) ||
(audio_format == AUDIO_FORMAT_AAC_LC) ||
(audio_format == AUDIO_FORMAT_AAC_HE_V1) ||
(audio_format == AUDIO_FORMAT_AAC_HE_V2) ||
(audio_format == AUDIO_FORMAT_AAC_LATM_LC) ||
(audio_format == AUDIO_FORMAT_AAC_LATM_HE_V1) ||
(audio_format == AUDIO_FORMAT_AAC_LATM_HE_V2)) {
*format = QAP_AUDIO_FORMAT_AAC_ADTS;
fprintf(stdout, "File Format is AAC!\n");
} else if (audio_format == AUDIO_FORMAT_DTS) {
*format = QAP_AUDIO_FORMAT_DTS;
fprintf(stdout, "File Format is DTS!\n");
} else if (audio_format == AUDIO_FORMAT_DTS_HD) {
*format = QAP_AUDIO_FORMAT_DTS_HD;
fprintf(stdout, "File Format is DTS_HD!\n");
} else if (audio_format == AUDIO_FORMAT_PCM_16_BIT) {
*format = QAP_AUDIO_FORMAT_PCM_16_BIT;
fprintf(stdout, "File Format is PCM_16!\n");
} else if (audio_format == AUDIO_FORMAT_PCM_32_BIT) {
*format = QAP_AUDIO_FORMAT_PCM_32_BIT;
fprintf(stdout, "File Format is PCM_32!\n");
} else if (audio_format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
*format = QAP_AUDIO_FORMAT_PCM_24_BIT_PACKED;
fprintf(stdout, "File Format is PCM_24!\n");
} else if ((audio_format == AUDIO_FORMAT_PCM_8_BIT) ||
(audio_format == AUDIO_FORMAT_PCM_8_24_BIT)) {
*format = QAP_AUDIO_FORMAT_PCM_8_24_BIT;
fprintf(stdout, "File Format is PCM_8_24!\n");
} else {
fprintf(stdout, "File Format not supported!\n");
return -EINVAL;
}
return 0;
}
char *get_string_value(const char *kvp, int *status)
{
char *tempstr1 = NULL;
char *tempstr2 = NULL;
char *l1;
char *ctx1;
if (kvp == NULL)
return NULL;
tempstr1 = strdup(kvp);
l1 = strtok_r(tempstr1, "=", &ctx1);
if (l1 != NULL) {
/* jump from key to value */
l1 = strtok_r(NULL, "=", &ctx1);
if (l1 != NULL)
tempstr2 = strdup(l1);
}
free(tempstr1);
return tempstr2;
}
int qap_wrapper_write_to_hal(qahw_stream_handle_t* out_handle, char *data, size_t bytes)
{
ssize_t ret;
qahw_out_buffer_t out_buf;
memset(&out_buf,0, sizeof(qahw_out_buffer_t));
out_buf.buffer = data;
out_buf.bytes = bytes;
ret = qahw_out_write(out_handle, &out_buf);
if (ret < 0)
fprintf(stderr, "%s::%d: writing data to hal failed (ret = %zd)\n", __func__, __LINE__, ret);
else if (ret != bytes)
fprintf(stdout, "%s::%d provided bytes %zd, written bytes %d\n",__func__, __LINE__, bytes, ret);
return ret;
}
static void close_output_streams()
{
int ret;
if (qap_out_hal_handle && qap_out_spk_handle) {
ret = qahw_out_standby(qap_out_spk_handle);
if (ret)
fprintf(stderr, "%s::%d: out standby failed %d \n", __func__, __LINE__, ret);
if (play_through_bt) {
fprintf(stdout, "%s::%d: disconnecting BT\n", __func__, __LINE__);
char param[100] = {0};
snprintf(param, sizeof(param), "%s=%d", "disconnect", AUDIO_DEVICE_OUT_BLUETOOTH_A2DP);
qahw_set_parameters(qap_out_hal_handle, param);
}
fprintf(stdout, "%s::%d: closing output stream\n", __func__, __LINE__);
ret = qahw_close_output_stream(qap_out_spk_handle);
if (ret)
fprintf(stderr, "%s::%d: could not close output stream, error - %d\n", __func__, __LINE__, ret);
qap_out_spk_handle = NULL;
}
if (qap_out_hal_handle && qap_out_hp_handle) {
ret = qahw_out_standby(qap_out_hp_handle);
if (ret)
fprintf(stderr, "%s::%d: out standby failed %d \n", __func__, __LINE__, ret);
fprintf(stdout, "%s::%d: closing output stream\n", __func__, __LINE__);
ret = qahw_close_output_stream(qap_out_hp_handle);
if (ret)
fprintf(stderr, "%s::%d: could not close output stream, error - %d\n", __func__, __LINE__, ret);
qap_out_hp_handle = NULL;
}
if (qap_out_hal_handle && qap_out_hdmi_handle) {
char param[100] = {0};
snprintf(param, sizeof(param), "%s=%d", "disconnect", AUDIO_DEVICE_OUT_HDMI);
ret = qahw_out_standby(qap_out_hdmi_handle);
if (ret)
fprintf(stderr, "%s::%d: out standby failed %d\n", __func__, __LINE__, ret);
qahw_set_parameters(qap_out_hal_handle, param);
fprintf(stdout, "%s::%d: closing output stream\n", __func__, __LINE__);
ret = qahw_close_output_stream(qap_out_hdmi_handle);
if (ret)
fprintf(stderr, "%s::%d: could not close output stream, error - %d\n", __func__, __LINE__, ret);
qap_out_hdmi_handle = NULL;
}
primary_stream_close = true;
}
void qap_wrapper_module_callback(qap_module_handle_t module_handle, void* priv_data, qap_module_callback_event_t event_id, int size, void *data)
{
stream_config *p_stream_param = (stream_config*)priv_data;
if(p_stream_param == NULL) {
ALOGE("%s %d, callback handle is null.",__func__,__LINE__);
}
ALOGV("%s %d, %s Received event id %d\n", __func__, __LINE__, p_stream_param->filename, event_id);
switch (event_id) {
case QAP_MODULE_CALLBACK_EVENT_SEND_INPUT_BUFFER:
{
if (size < sizeof(qap_send_buffer_t)) {
ALOGE("%s %d event id %d, wrong payload size %d\n",
__func__, __LINE__, event_id, size);
break;
}
qap_send_buffer_t *p_send_buffer_event = (qap_send_buffer_t*)data;
pthread_mutex_lock(&p_stream_param->input_buffer_available_lock);
p_stream_param->input_buffer_available_size = p_send_buffer_event->bytes_available;
pthread_cond_signal(&p_stream_param->input_buffer_available_cond);
pthread_mutex_unlock(&p_stream_param->input_buffer_available_lock);
break;
}
case QAP_MODULE_CALLBACK_EVENT_INPUT_CFG_CHANGE:
{
if (size < sizeof(qap_input_config_t)) {
ALOGE("%s %d event id %d, wrong payload size %d\n",
__func__, __LINE__, event_id, size);
break;
}
qap_input_config_t *p_stream_format = (qap_input_config_t*)data;
ALOGV(" %s %d Input format updated; sample_rate %lu, channels %lu, bitwidth %lu",
__func__, __LINE__,
p_stream_format->sample_rate,
p_stream_format->channels,
p_stream_format->bit_width);
break;
}
default:
break;
}
}
void qap_wrapper_session_callback(qap_session_handle_t session_handle __unused, void* priv_data __unused, qap_callback_event_t event_id, int size, void *data)
{
int ret = 0;
int bytes_written = 0;
int bytes_remaining = 0;
int offset = 0;
audio_output_flags_t flags;
flags = (AUDIO_OUTPUT_FLAG_NON_BLOCKING |
AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD |
AUDIO_OUTPUT_FLAG_DIRECT);
ALOGV("%s %d Received event id %d\n", __func__, __LINE__, event_id);
switch (event_id) {
case QAP_CALLBACK_EVENT_EOS:
ALOGV("%s %d Received Main Input EOS", __func__, __LINE__);
if (stream_cnt > 0)
stream_cnt--;
pthread_mutex_lock(&main_eos_lock);
pthread_cond_signal(&main_eos_cond);
main_eos_received = true;
pthread_mutex_unlock(&main_eos_lock);
if (!stream_cnt)
close_output_streams();
if (play_list_cnt && input_streams_count) {
play_list_cnt--;
input_streams_count = 0;
}
break;
case QAP_CALLBACK_EVENT_EOS_ASSOC:
if (stream_cnt > 0)
stream_cnt--;
//if (!has_system_input)
{
ALOGV("%s %d Received Secondary Input EOS", __func__, __LINE__);
pthread_mutex_lock(&sec_eos_lock);
pthread_cond_signal(&sec_eos_cond);
sec_eos_received = true;
pthread_mutex_unlock(&sec_eos_lock);
}
if (!stream_cnt)
close_output_streams();
break;
case QAP_CALLBACK_EVENT_MAIN_2_EOS:
if (stream_cnt > 0)
stream_cnt--;
//if (!has_system_input)
{
ALOGV("%s %d Received main2 Input EOS", __func__, __LINE__);
pthread_mutex_lock(&main2_eos_lock);
pthread_cond_signal(&main2_eos_cond);
main2_eos_received = true;
pthread_mutex_unlock(&main2_eos_lock);
}
if (!stream_cnt)
close_output_streams();
break;
case QAP_CALLBACK_EVENT_ERROR:
break;
case QAP_CALLBACK_EVENT_SUCCESS:
break;
case QAP_CALLBACK_EVENT_METADATA:
break;
case QAP_CALLBACK_EVENT_OUTPUT_CFG_CHANGE:
if (data != NULL) {
qap_audio_buffer_t *buffer = (qap_audio_buffer_t *) data;
qap_output_config_t *new_conf = &buffer->buffer_parms.output_buf_params.output_config;
qap_output_config_t *cached_conf = NULL;
int index = -1;
ALOGV("%s %d Received Output cfg change", __func__, __LINE__);
if (buffer) {
index = get_qap_session_out_config_index_for_id(
buffer->buffer_parms.output_buf_params.output_id);
if (index >= 0)
cached_conf = &session_output_config.output_config[index];
}
if (cached_conf == NULL) {
ALOGE("Invalid output config from QAP is reached");
return;
}
if (memcmp(cached_conf, new_conf, sizeof(qap_output_config_t)) != 0) {
memcpy(cached_conf, new_conf, sizeof(qap_output_config_t));
cached_conf->id = buffer->buffer_parms.output_buf_params.output_id;
is_media_fmt_changed[index] = true;
}
}
break;
case QAP_CALLBACK_EVENT_DATA:
if (data != NULL) {
qap_audio_buffer_t *buffer = (qap_audio_buffer_t *) data;
if (buffer && timestamp_mode) {
char ch[100] = {0};
if (kpi_mode) {
if ((data_callback_count > 5) && (data_callback_count < TIMESTAMP_ARRAY_SIZE)) {
gettimeofday(&tcont_ts2, NULL);
data_callback_ts_arr[data_callback_count] = buffer->common_params.timestamp;
data_callback_st_arr[data_callback_count] = (tcont_ts2.tv_sec) * 1000 + (tcont_ts2.tv_usec) / 1000;
ALOGV("%s::%d data size %d, Kpi cont ts2 %lf, buffer timestamp %ld",
__func__, __LINE__, buffer->common_params.size,
data_callback_st_arr[data_callback_count], data_callback_ts_arr[data_callback_count]);
}
if (data_callback_count < TIMESTAMP_ARRAY_SIZE)
data_callback_count++;
}
if (fp_output_timestamp_file == NULL) {
fp_output_timestamp_file =
fopen("/sdcard/output_timestamp_file.txt","w");
if(fp_output_timestamp_file) {
fprintf(stdout, "output file :: "
"/sdcard/output_file_timestamp.txt"
" has been generated.");
}
}
if (fp_output_timestamp_file) {
sprintf(ch, "%d,%lld\n", buffer->common_params.size, buffer->common_params.timestamp);
fprintf(stdout, "%s: %s", __func__, ch);
ret = fwrite((char *)&ch, sizeof(char),
strlen(ch), fp_output_timestamp_file);
fflush(fp_output_timestamp_file);
}
}
if (buffer && buffer->common_params.data) {
int index = -1;
bool is_reopen_stream = false;
index = get_qap_session_out_config_index_for_id(buffer->buffer_parms.output_buf_params.output_id);
if (index > -1 && is_media_fmt_changed[index]) {
is_reopen_stream = true;
is_media_fmt_changed[index] = false;
} else if (index < 0) {
ALOGE("%s: No Valid Output Config found for id = %d",
__func__, buffer->buffer_parms.output_buf_params.output_id);
break;
}
if ((buffer->buffer_parms.output_buf_params.output_id &
AUDIO_DEVICE_OUT_HDMI) == AUDIO_DEVICE_OUT_HDMI) {
if (!hdmi_connected) {
char param[100] = {0};
snprintf(param, sizeof(param), "%s=%d", "connect", AUDIO_DEVICE_OUT_HDMI);
qahw_set_parameters(qap_out_hal_handle, param);
hdmi_connected = true;
}
if (encode) {
if (enable_dump && fp_output_writer_hdmi == NULL) {
if (buffer->buffer_parms.output_buf_params.output_id ==
(AUDIO_FORMAT_E_AC3|AUDIO_DEVICE_OUT_HDMI))
qap_wrapper_create_multi_channel_dump("/sdcard/output_hdmi.ddp");
else if (buffer->buffer_parms.output_buf_params.output_id ==
(AUDIO_FORMAT_AC3|AUDIO_DEVICE_OUT_HDMI))
qap_wrapper_create_multi_channel_dump("/sdcard/output_hdmi.dd");
else
qap_wrapper_create_multi_channel_dump("/sdcard/output_hdmi_dts.dts");
}
} else {
if (enable_dump && fp_output_writer_hdmi == NULL)
qap_wrapper_create_multi_channel_dump("/sdcard/output_hdmi.dump");
}
if (fp_output_writer_hdmi) {
ret = fwrite((unsigned char *)buffer->common_params.data, sizeof(unsigned char),
buffer->common_params.size, fp_output_writer_hdmi);
fflush(fp_output_writer_hdmi);
}
if (is_reopen_stream && qap_out_hdmi_handle) {
qahw_close_output_stream(qap_out_hdmi_handle);
qap_out_hdmi_handle = NULL;
is_reopen_stream = false;
}
if (hdmi_connected && qap_out_hdmi_handle == NULL) {
struct audio_config config;
audio_devices_t devices;
config.offload_info.version = AUDIO_INFO_INITIALIZER.version;
config.offload_info.size = AUDIO_INFO_INITIALIZER.size;
config.sample_rate = config.offload_info.sample_rate = DEFAULT_SAMPLE_RATE;
if (index > -1) {
if (session_output_config.output_config[index].sample_rate > 0)
config.sample_rate = config.offload_info.sample_rate = session_output_config.output_config[index].sample_rate;
config.offload_info.channel_mask = config.channel_mask =
audio_channel_out_mask_from_count(session_output_config.output_config[index].channels);
if (session_output_config.output_config[index].bit_width == 24) {
config.format = config.offload_info.format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
config.offload_info.bit_width = 24;
} else {
config.format = config.offload_info.format = AUDIO_FORMAT_PCM_16_BIT;
config.offload_info.bit_width = 16;
}
if (session_output_config.output_config[index].format == QAP_AUDIO_FORMAT_AC3)
config.format = config.offload_info.format = AUDIO_FORMAT_AC3;
else if (session_output_config.output_config[index].format == QAP_AUDIO_FORMAT_EAC3)
config.format = config.offload_info.format = AUDIO_FORMAT_E_AC3;
else if (session_output_config.output_config[index].format == QAP_AUDIO_FORMAT_DTS)
config.format = config.offload_info.format = AUDIO_FORMAT_DTS;
}
devices = AUDIO_DEVICE_OUT_HDMI;
if (timestamp_mode)
flags |= AUDIO_OUTPUT_FLAG_TIMESTAMP;
if (encode) {
ALOGV("%s:%d output format %x", __func__, __LINE__,
config.format, config.offload_info.format);
ret = qahw_open_output_stream(qap_out_hal_handle, qap_stream_out_cmpr_handle, devices,
flags, &config, &qap_out_hdmi_handle, "stream");
} else {
ret = qahw_open_output_stream(qap_out_hal_handle, qap_stream_out_hdmi_handle, devices,
flags, &config, &qap_out_hdmi_handle, "stream");
if (index > -1)
set_qahw_stream_channel_map(qap_out_hdmi_handle, &session_output_config.output_config[index]);
}
ret = qahw_out_set_volume(qap_out_hdmi_handle, vol_level, vol_level);
if (ret < 0)
ALOGE("unable to set volume");
}
if (qap_out_hdmi_handle) {
bytes_written = qap_wrapper_write_to_hal(qap_out_hdmi_handle,
buffer->common_params.data, buffer->common_params.size);
if (bytes_written == -1) {
ALOGE("%s::%d write failed in hal", __func__, __LINE__);
}
if (kpi_mode && data_callback_count == 6)
dsp_latency = qahw_out_get_latency(qap_out_hdmi_handle);
}
if (kpi_mode && data_callback_count == 1) {
gettimeofday(&tcold_stop, NULL);
cold_stop = (tcold_stop.tv_sec) * 1000 + (tcold_stop.tv_usec) / 1000;
ALOGD("%s::%d Measuring Kpi cold stop %lf", __func__, __LINE__, cold_stop);
}
}
if (buffer->buffer_parms.output_buf_params.output_id == AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
buffer->buffer_parms.output_buf_params.output_id == AUDIO_DEVICE_OUT_LINE) {
if (enable_dump && fp_output_writer_hp == NULL) {
fp_output_writer_hp =
fopen("/sdcard/output_hp.dump","wb");
if (fp_output_writer_hp) {
fprintf(stdout, "output file :: "
"/sdcard/output_hp.dump"
" has been generated.\n");
} else {
fprintf(stderr, "Failed open hp dump file\n");
}
}
if (fp_output_writer_hp) {
ret = fwrite((unsigned char *)buffer->common_params.data, sizeof(unsigned char),
buffer->common_params.size, fp_output_writer_hp);
fflush(fp_output_writer_hp);
}
if (is_reopen_stream && qap_out_hp_handle) {
qahw_close_output_stream(qap_out_hp_handle);
qap_out_hp_handle = NULL;
is_reopen_stream = false;
}
if (qap_out_hp_handle == NULL) {
struct audio_config config;
audio_devices_t devices;
config.offload_info.version = AUDIO_INFO_INITIALIZER.version;
config.offload_info.size = AUDIO_INFO_INITIALIZER.size;
config.sample_rate = config.offload_info.sample_rate = DEFAULT_SAMPLE_RATE;
config.format = config.offload_info.format = AUDIO_FORMAT_PCM_16_BIT;
config.offload_info.bit_width = 16;
config.offload_info.channel_mask = config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
if (index > -1) {
config.sample_rate = config.offload_info.sample_rate = session_output_config.output_config[index].sample_rate;
config.offload_info.channel_mask = config.channel_mask =
audio_channel_out_mask_from_count(session_output_config.output_config[index].channels);
if (session_output_config.output_config[index].bit_width == 24) {
config.format = config.offload_info.format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
config.offload_info.bit_width = 24;
}
}
devices = AUDIO_DEVICE_OUT_LINE;//ToDO - Need to change to AUDIO_DEVICE_OUT_WIRED_HEADPHONE
if (timestamp_mode)
flags |= AUDIO_OUTPUT_FLAG_TIMESTAMP;
ret = qahw_open_output_stream(qap_out_hal_handle, qap_stream_out_hp_handle, devices,
flags, &config, &qap_out_hp_handle, "stream");
if (ret) {
ALOGE("%s:%d could not open output stream, error - %d", __func__, __LINE__, ret);
return;
}
if (index > -1)
set_qahw_stream_channel_map(qap_out_hp_handle, &session_output_config.output_config[index]);
ret = qahw_out_set_volume(qap_out_hp_handle, vol_level, vol_level);
if (ret < 0)
ALOGE("unable to set volume");
}
if (qap_out_hp_handle) {
bytes_written = qap_wrapper_write_to_hal(qap_out_hp_handle,
buffer->common_params.data, buffer->common_params.size);
if (bytes_written == -1) {
ALOGE("%s::%d write failed in hal", __func__, __LINE__);
}
if (kpi_mode && data_callback_count == 6)
dsp_latency = qahw_out_get_latency(qap_out_hp_handle);
}
if (kpi_mode && data_callback_count == 1) {
gettimeofday(&tcold_stop, NULL);
cold_stop = (tcold_stop.tv_sec) * 1000 + (tcold_stop.tv_usec) / 1000;
ALOGD("%s::%d Measuring Kpi cold stop %lf", __func__, __LINE__, cold_stop);
}
}
if (buffer->buffer_parms.output_buf_params.output_id == AUDIO_DEVICE_OUT_SPEAKER) {
if (enable_dump && fp_output_writer_spk == NULL) {
char ch[4] = {0};
fp_output_writer_spk =
fopen("/sdcard/output_speaker.dump","wb");
if (fp_output_writer_spk) {
fprintf(stdout, "output file :: "
"/sdcard/output_speaker.dump"
" has been generated.\n");
if (dolby_formats) {
ret = fwrite((unsigned char *)&ch, sizeof(unsigned char),
4, fp_output_writer_spk);
}
} else {
fprintf(stderr, "Failed open speaker dump file\n");
}
}
if (fp_output_writer_spk) {
ret = fwrite((unsigned char *)buffer->common_params.data, sizeof(unsigned char),
buffer->common_params.size, fp_output_writer_spk);
fflush(fp_output_writer_spk);
}
if (is_reopen_stream && qap_out_spk_handle) {
qahw_close_output_stream(qap_out_spk_handle);
qap_out_spk_handle = NULL;
is_reopen_stream = false;
}
if (qap_out_spk_handle == NULL) {
struct audio_config config;
audio_devices_t devices;
config.offload_info.version = AUDIO_INFO_INITIALIZER.version;
config.offload_info.size = AUDIO_INFO_INITIALIZER.size;
config.sample_rate = config.offload_info.sample_rate = DEFAULT_SAMPLE_RATE;
config.format = config.offload_info.format = AUDIO_FORMAT_PCM_16_BIT;
config.offload_info.bit_width = 16;
config.offload_info.channel_mask = config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
if (index > -1) {
config.sample_rate = config.offload_info.sample_rate = session_output_config.output_config[index].sample_rate;
config.offload_info.channel_mask = config.channel_mask =
audio_channel_out_mask_from_count(session_output_config.output_config[index].channels);
if (session_output_config.output_config[index].bit_width == 24) {
config.format = config.offload_info.format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
config.offload_info.bit_width = 24;
}
}
if (play_through_bt) {
fprintf(stderr, "%s::%d: connecting BT\n", __func__, __LINE__);
char param[100] = {0};
snprintf(param, sizeof(param), "%s=%d", "connect", AUDIO_DEVICE_OUT_BLUETOOTH_A2DP);
qahw_set_parameters(qap_out_hal_handle, param);
devices = AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
} else {
devices = AUDIO_DEVICE_OUT_SPEAKER;
}
if (timestamp_mode)
flags |= AUDIO_OUTPUT_FLAG_TIMESTAMP;
ALOGD("%s::%d: open output for device %d", __func__, __LINE__, devices);
ret = qahw_open_output_stream(qap_out_hal_handle, qap_stream_out_spk_handle, devices,
flags, &config, &qap_out_spk_handle, "stream");
if (ret) {
ALOGE("%s:%d could not open output stream, error - %d", __func__, __LINE__, ret);
return;
}
if (index > -1)
set_qahw_stream_channel_map(qap_out_spk_handle, &session_output_config.output_config[index]);
ret = qahw_out_set_volume(qap_out_spk_handle, vol_level, vol_level);
if (ret < 0)
ALOGE("unable to set volume");
}
if (qap_out_spk_handle) {
bytes_written = qap_wrapper_write_to_hal(qap_out_spk_handle,
buffer->common_params.data, buffer->common_params.size);
if (bytes_written == -1) {
ALOGE("%s::%d write failed in hal", __func__, __LINE__);
}
if (kpi_mode && data_callback_count == 6)
dsp_latency = qahw_out_get_latency(qap_out_spk_handle);
}
if (kpi_mode && data_callback_count == 1) {
gettimeofday(&tcold_stop, NULL);
cold_stop = (tcold_stop.tv_sec) * 1000 + (tcold_stop.tv_usec) / 1000;
ALOGD("%s::%d Measuring Kpi cold stop %lf", __func__, __LINE__, cold_stop);
}
}
if (buffer->buffer_parms.output_buf_params.output_id == AUDIO_DEVICE_OUT_PROXY) {
if (fp_ecref == NULL) {
fp_ecref = fopen("/data/vendor/misc/audio/ecref", "w+");
}
if (fp_ecref) {
ALOGD("%s: write %d bytes to ecref dump",__func__,buffer->common_params.size);
fwrite((unsigned char *)buffer->common_params.data, 1, buffer->common_params.size, fp_ecref);
} else {
ALOGE("%s: failed to open ecref dump file",__func__);
}
}
}
}
break;
default:
break;
}
}
static void qap_wrapper_is_dap_enabled(char *kv_pairs, int out_device_id, qap_session_handle_t handle) {
int status = 0;
int temp = 0;
char *dap_kvp = NULL;
int *dap_value = NULL;
int dap_enable = 0;
qap_session_pp_configs_t dap_pp_config;
dap_kvp = qap_wrapper_get_single_kvp("dap_enable", kv_pairs, &status);
if (dap_kvp != NULL) {
dap_value = qap_wrapper_get_int_value_array(dap_kvp, &temp, &status);
if (dap_value != NULL)
dap_enable = dap_value[0];
if (dap_enable) {
fprintf(stdout, "dap enable %d and device id %d\n", dap_enable, out_device_id);
char *dev_kvp = NULL;
if ((out_device_id & AUDIO_DEVICE_OUT_SPEAKER) == AUDIO_DEVICE_OUT_SPEAKER) {
dev_kvp = (char *) calloc(1, status + strlen("o_device=1; "));
if (dev_kvp != NULL) {
strcat(dev_kvp, "o_device=1;");
strcat(session_kv_pairs, dev_kvp);
fprintf(stdout, "session set params %s\n", session_kv_pairs);
free(dev_kvp);
dev_kvp = NULL;
}
dap_pp_config.pp_config[dap_pp_config.num_confs].id = AUDIO_DEVICE_OUT_SPEAKER;
dlb_param = MS12_SESSION_CFG_DAP_ENABLE_SPEAKER;
dap_pp_config.pp_config[dap_pp_config.num_confs].pp_type = (void *) &dlb_param;
dap_pp_config.num_confs++;
}
if (((out_device_id & AUDIO_DEVICE_OUT_LINE) == AUDIO_DEVICE_OUT_LINE) ||
((out_device_id & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
dev_kvp = (char *) calloc(1, status + strlen("o_device=2; "));
if (dev_kvp != NULL) {
strcat(dev_kvp, "o_device=2;");
strcat(session_kv_pairs, dev_kvp);
fprintf(stdout, "session set params %s\n", session_kv_pairs);
free(dev_kvp);
dev_kvp = NULL;
}
if ((out_device_id & AUDIO_DEVICE_OUT_LINE) == AUDIO_DEVICE_OUT_LINE)
dap_pp_config.pp_config[dap_pp_config.num_confs].id = AUDIO_DEVICE_OUT_LINE;
else
dap_pp_config.pp_config[dap_pp_config.num_confs].id = AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
dlb_param_hp = MS12_SESSION_CFG_DAP_ENABLE_HEADPHONE;
dap_pp_config.pp_config[dap_pp_config.num_confs].pp_type = (void *) &dlb_param_hp;
dap_pp_config.num_confs++;
}
status = qap_session_cmd(qap_session_handle, QAP_SESSION_CMD_SET_PP_OUTPUTS,
sizeof(qap_session_pp_configs_t), &dap_pp_config, NULL, NULL);
if (status != QAP_STATUS_OK)
fprintf(stderr, "Output config failed\n");
}
free(dap_kvp);
dap_kvp = NULL;
}
}
void update_qap_session_init_params(char *kv_pairs)
{
int status = 0;
char *kvp = NULL;
int temp = 0;
int *temp_val = NULL;
uint32_t cmd_data[16] = {0};
uint32_t cmd_size = 0;
kvp = qap_wrapper_get_single_kvp("max_chs", kv_pairs, &status);
if (kvp != NULL) {
temp_val = qap_wrapper_get_int_value_array(kvp, &temp, &status);
if (temp_val != NULL) {
cmd_data[cmd_size++] = MS12_SESSION_CFG_MAX_CHS;
cmd_data[cmd_size++] = temp_val[0];
free(temp_val);
temp_val = NULL;
}
free(kvp);
kvp = NULL;
}
kvp = qap_wrapper_get_single_kvp("bs_out_mode", kv_pairs, &status);
if (kvp != NULL) {
temp_val = qap_wrapper_get_int_value_array(kvp, &temp, &status);
if (temp_val != NULL) {
cmd_data[cmd_size++] = MS12_SESSION_CFG_BS_OUTPUT_MODE;
cmd_data[cmd_size++] = temp_val[0];
free(temp_val);
temp_val = NULL;
}
free(kvp);
kvp = NULL;
}
kvp = qap_wrapper_get_single_kvp("chmod_locking", kv_pairs, &status);
if (kvp != NULL) {
temp_val = qap_wrapper_get_int_value_array(kvp, &temp, &status);
if (temp_val != NULL) {
cmd_data[cmd_size++] = MS12_SESSION_CFG_CHMOD_LOCKING;
cmd_data[cmd_size++] = temp_val[0];
free(temp_val);
temp_val = NULL;
}
free(kvp);
kvp = NULL;
}
kvp = qap_wrapper_get_single_kvp("dn", kv_pairs, &status);
if (kvp != NULL) {
temp_val = qap_wrapper_get_int_value_array(kvp, &temp, &status);
if (temp_val != NULL) {
cmd_data[cmd_size++] = MS12_SESSION_CFG_DIALOG_NORM;
cmd_data[cmd_size++] = temp_val[0];
free(temp_val);
temp_val = NULL;
}
free(kvp);
kvp = NULL;
}
kvp = qap_wrapper_get_single_kvp("rp", kv_pairs, &status);
if (kvp != NULL) {
temp_val = qap_wrapper_get_int_value_array(kvp, &temp, &status);
if (temp_val != NULL) {
cmd_data[cmd_size++] = MS12_SESSION_CFG_COMPR_PROF;
cmd_data[cmd_size++] = temp_val[0];
free(temp_val);
temp_val = NULL;
}
free(kvp);
kvp = NULL;
}
if (!cmd_size) {
return;
}
temp = qap_session_cmd(qap_session_handle,
QAP_SESSION_CMD_SET_PARAM,
cmd_size * sizeof(uint32_t),
&cmd_data[0],
NULL,
NULL);
if (temp != QAP_STATUS_OK) {
fprintf(stderr, "session init config failed\n");
}
}
int qap_wrapper_session_open(char *kv_pairs, void* stream_data, int num_of_streams, qahw_module_handle_t *hal_handle)
{
int status = 0;
int ret = 0;
int i;
int temp = 0;
stream_config *stream = (stream_config *)stream_data;
char *session_type_kvp = NULL;
char *encode_kvp = NULL;
int *temp_val = NULL;
char *bitwidth_kvp = NULL;
int out_bitwidth = PCM_16_BITWIDTH;
int out_sample_rate = DEFAULT_SAMPLE_RATE;
qap_out_hal_handle = hal_handle;
if (kpi_mode) {
memset(data_input_st_arr, 0, sizeof(data_input_st_arr));
memset(data_input_ts_arr, 0, sizeof(data_input_ts_arr));
memset(data_callback_st_arr, 0, sizeof(data_callback_st_arr));
memset(data_callback_ts_arr, 0, sizeof(data_callback_ts_arr));
gettimeofday(&tcold_start, NULL);
cold_start = (tcold_start.tv_sec) * 1000 + (tcold_start.tv_usec) / 1000;
ALOGD("%s::%d Measuring Kpi cold start %lf", __func__, __LINE__, cold_start);
}
if (play_list)
play_list_cnt = num_of_streams;
memset(&session_output_config, 0, sizeof(session_output_config));
strcpy(session_kv_pairs, kv_pairs);
ALOGV("%s session_kv_pairs = %s", __func__, session_kv_pairs);
if (NULL != (session_type_kvp = qap_wrapper_get_single_kvp("broadcast", kv_pairs, &status))) {
session_type = SESSION_BROADCAST;
fprintf(stdout, "Session Type is Broadcast\n");
free(session_type_kvp);
session_type_kvp = NULL;
} else if (NULL != (session_type_kvp = qap_wrapper_get_single_kvp("bd", kv_pairs, &status))) {
session_type = SESSION_BLURAY;
free(session_type_kvp);
session_type_kvp = NULL;
fprintf(stdout, "Session Type is Bluray\n");
}
if (session_type == SESSION_BLURAY) {
if ((stream->filetype == FILE_WAV) ||
(stream->filetype == FILE_AAC)) {
fprintf(stderr, "Format is not supported for BD usecase\n");
return -EINVAL;
}
if (!play_list && num_of_streams > 1) {
fprintf(stderr, "Please specifiy proper session type\n");
return -EINVAL;
}
}
if (stream->filetype == FILE_DTS && (NULL == m8_lib_handle)) {
m8_lib_handle = (qap_session_handle_t) qap_load_library(QAC_LIB_M8);
if (m8_lib_handle == NULL) {
fprintf(stdout, "Failed to load M8 library\n");
return -EINVAL;
}
fprintf(stdout, "loaded M8 library\n");
dolby_formats = false;
} else if ((stream->filetype == FILE_AC3) ||
(stream->filetype == FILE_EAC3) ||
(stream->filetype == FILE_EAC3_JOC) ||
(stream->filetype == FILE_WAV) ||
(stream->filetype == FILE_AAC) ||
(stream->filetype == FILE_AAC_ADTS) ||
(stream->filetype == FILE_AAC_LATM) && (NULL == ms12_lib_handle)) {
ms12_lib_handle = (qap_session_handle_t) qap_load_library(QAC_LIB_MS12);
if (ms12_lib_handle == NULL) {
fprintf(stderr, "Failed to load MS12 library\n");
return -EINVAL;
}
dolby_formats = true;
}
// To-Do - Need to check SPDIF out also when SPDIF out is supported
ALOGD("%s::%d output device %d", __func__, __LINE__, stream->output_device);
bitwidth_kvp = qap_wrapper_get_single_kvp("bitwidth", kv_pairs, &status);
if (bitwidth_kvp != NULL) {
temp_val = qap_wrapper_get_int_value_array(bitwidth_kvp, &temp, &status);
if (temp_val != NULL) {
if (stream->filetype == FILE_DTS)
out_bitwidth = temp_val[0];
free(temp_val);
temp_val = NULL;
}
free(bitwidth_kvp);
bitwidth_kvp = NULL;
}
if ((session_type == SESSION_BROADCAST) && dolby_formats) {
fprintf(stdout, "%s::%d Setting BROADCAST session for dolby formats\n", __func__, __LINE__);
qap_session_handle = (qap_session_handle_t) qap_session_open(QAP_SESSION_MS12_OTT, ms12_lib_handle);
if (qap_session_handle == NULL)
return -EINVAL;
} else if ((session_type == SESSION_BROADCAST) && !dolby_formats) {
fprintf(stdout, "%s::%d Setting BROADCAST session for dts formats\n", __func__, __LINE__);
qap_session_handle = (qap_session_handle_t) qap_session_open(QAP_SESSION_BROADCAST, m8_lib_handle);
if (qap_session_handle == NULL)
return -EINVAL;
} else if (session_type == SESSION_BLURAY) {
fprintf(stdout, "%s::%d Setting BD session\n", __func__, __LINE__);
if (!encode && dolby_formats) {
fprintf(stdout, "%s::%d Setting BD session for decoding dolby formats\n", __func__, __LINE__);
qap_session_handle = (qap_session_handle_t) qap_session_open(QAP_SESSION_DECODE_ONLY, ms12_lib_handle);
if (qap_session_handle == NULL)
return -EINVAL;
} else if (!encode && !dolby_formats) {
fprintf(stdout, "%s::%d Setting BD session for decoding dts formats \n", __func__, __LINE__, qap_session_handle);
qap_session_handle = (qap_session_handle_t) qap_session_open(QAP_SESSION_DECODE_ONLY, m8_lib_handle);
if (qap_session_handle == NULL)
return -EINVAL;
} else if (encode && dolby_formats) {
fprintf(stdout, "%s::%d Setting BD session for encoding dolby formats \n", __func__, __LINE__, qap_session_handle);
qap_session_handle = (qap_session_handle_t) qap_session_open(QAP_SESSION_ENCODE_ONLY, ms12_lib_handle);
if (qap_session_handle == NULL)
return -EINVAL;
} else if (encode && !dolby_formats) {
fprintf(stdout, "%s::%d Setting BD session for encoding dts formats \n", __func__, __LINE__, qap_session_handle);
qap_session_handle = (qap_session_handle_t) qap_session_open(QAP_SESSION_ENCODE_ONLY, m8_lib_handle);
if (qap_session_handle == NULL)
return -EINVAL;
}
}
ret = qap_session_set_callback(qap_session_handle, &qap_wrapper_session_callback, NULL);
if (ret != QAP_STATUS_OK) {
fprintf(stderr, "!!!! Please specify appropriate Session\n");
return -EINVAL;
}
if (dolby_formats) {
update_qap_session_init_params(kv_pairs);
}
if (!session_output_configured) {
if (session_type != SESSION_BROADCAST)
out_sample_rate = stream->config.sample_rate;;
output_device_id = stream->output_device;
if (output_device_id & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) {
output_device_id |= AUDIO_DEVICE_OUT_SPEAKER;
play_through_bt = true;
}
update_session_outputs_config(render_format, stream->channels, out_bitwidth, out_sample_rate);
ret = qap_session_cmd(qap_session_handle, QAP_SESSION_CMD_SET_OUTPUTS, sizeof(session_output_config), &session_output_config, NULL, NULL);
if (ret != QAP_STATUS_OK) {
fprintf(stderr, "Output config failed\n");
return -EINVAL;
}
qap_wrapper_is_dap_enabled(kv_pairs, stream->output_device, qap_session_handle);
bitwidth_kvp = qap_wrapper_get_single_kvp("k", kv_pairs, &status);
if (bitwidth_kvp && strncmp(bitwidth_kvp, "k=", 2) == 0) {
fprintf(stdout, "Session set params, kvpair %s\n",&bitwidth_kvp[2]);
ret = qap_session_cmd(qap_session_handle, QAP_SESSION_CMD_SET_KVPAIRS, (sizeof(bitwidth_kvp) - 2), &bitwidth_kvp[2], NULL, NULL);
if (ret != QAP_STATUS_OK)
fprintf(stderr, "Session set params failed\n");
}
usleep(2000);
session_output_configured = true;
}
pthread_mutex_init(&main_eos_lock, (const pthread_mutexattr_t *)NULL);
pthread_mutex_init(&main2_eos_lock, (const pthread_mutexattr_t *)NULL);
pthread_mutex_init(&sec_eos_lock, (const pthread_mutexattr_t *)NULL);
pthread_cond_init(&main_eos_cond, (const pthread_condattr_t *) NULL);
pthread_cond_init(&main2_eos_cond, (const pthread_condattr_t *) NULL);
pthread_cond_init(&sec_eos_cond, (const pthread_condattr_t *) NULL);
fprintf(stdout, "Session open returing success\n");
return 0;
}
int qap_wrapper_session_close ()
{
ALOGD("closing QAP session");
session_output_configured = false;
qap_session_close(qap_session_handle);
qap_session_handle = NULL;
if (stream_cnt == 0) {
if (NULL != m8_lib_handle) {
qap_unload_library(m8_lib_handle);
m8_lib_handle = NULL;
}
if (NULL != ms12_lib_handle) {
qap_unload_library(ms12_lib_handle);
ms12_lib_handle = NULL;
}
}
}
void *qap_wrapper_start_stream (void* stream_data)
{
int ret = 0;
qap_audio_buffer_t *buffer;
int8_t first_read = 1;
int bytes_wanted;
int bytes_read;
int bytes_consumed = 0, status = 0;;
qap_module_handle_t qap_module_handle = NULL;
stream_config *stream_info = (stream_config *)stream_data;
FILE *fp_input = stream_info->file_stream;
int is_buffer_available = 0;
char *temp_str = NULL;
void *reply_data;
char* temp_ptr = NULL;
qap_audio_format_t format;
if (fp_input == NULL) {
fprintf(stderr, "Open File Failed for %s\n", stream_info->filename);
return NULL;
}
qap_module_handle = stream_info->qap_module_handle;
buffer = (qap_audio_buffer_t *) calloc(1, sizeof(qap_audio_buffer_t));
if (buffer == NULL) {
fprintf(stderr, "%s::%d: Memory Alloc Error\n", __func__, __LINE__);
return NULL;
}
buffer->common_params.data = calloc(1, FRAME_SIZE);
if (buffer->common_params.data == NULL) {
fprintf(stderr, "%s::%d: Memory Alloc Error\n", __func__, __LINE__);
if (NULL != buffer) {
free( buffer);
buffer = NULL;
}
return NULL;
}
buffer->buffer_parms.output_buf_params.output_id = output_device_id;
fprintf(stdout, "%s::%d: output device id %d\n",
__func__, __LINE__, buffer->buffer_parms.output_buf_params.output_id);
fprintf(stdout, "Opened Input File %s format %d handle %p\n", stream_info->filename, format, fp_input);
ret = qap_module_cmd(qap_module_handle, QAP_MODULE_CMD_START, sizeof(QAP_MODULE_CMD_START), NULL, NULL, NULL);
if (ret != QAP_STATUS_OK) {
fprintf(stderr, "START failed\n");
if (NULL != buffer && NULL != buffer->common_params.data) {
free( buffer->common_params.data);
buffer->common_params.data = NULL;
free( buffer);
buffer = NULL;
}
return NULL;
}
do {
if (stream_info->filetype == FILE_WAV) {
if (first_read) {
first_read = 0;
int wav_header_len = get_wav_header_length(stream_info->file_stream);
fseek(fp_input, wav_header_len, SEEK_SET);
}
if (stream_info->channels > 6)
stream_info->bytes_to_read = (FRAME_SIZE_FOR_2CH_PCM * 4);
else
stream_info->bytes_to_read = (FRAME_SIZE_FOR_2CH_PCM * 3);
}
buffer->buffer_parms.input_buf_params.flags = QAP_BUFFER_NO_TSTAMP;
buffer->common_params.timestamp = QAP_BUFFER_NO_TSTAMP;
buffer->common_params.size = stream_info->bytes_to_read;
if (stream_info->timestamp_filename != NULL) {
if (!stream_info->timestamp_file_ptr) {
stream_info->timestamp_file_ptr = fopen(stream_info->timestamp_filename, "r");
if (!stream_info->timestamp_file_ptr) {
fprintf(stderr, "Cannot open audio file %s\n", stream_info->filename);
goto exit;
}
}
read_bytes_timestamps_from_file(buffer, stream_info->timestamp_file_ptr, fp_input);
if (buffer->common_params.timestamp == CONTIGUOUS_TIMESTAMP)
buffer->buffer_parms.input_buf_params.flags = QAP_BUFFER_TSTAMP_CONTINUE;
else
buffer->buffer_parms.input_buf_params.flags = QAP_BUFFER_TSTAMP;
timestamp_mode = true;
}
bytes_wanted = buffer->common_params.size;
bytes_read = fread(buffer->common_params.data, sizeof(unsigned char), bytes_wanted, fp_input);
buffer->common_params.offset = 0;
buffer->common_params.size = bytes_read;
//memcpy(buffer->common_params.data, data_buf, bytes_read);
if (bytes_read <= 0 || stop_playback) {
buffer->buffer_parms.input_buf_params.flags = QAP_BUFFER_EOS;
bytes_consumed = qap_module_process(qap_module_handle, buffer);
if (stop_playback)
qap_module_cmd(qap_module_handle, QAP_MODULE_CMD_FLUSH, sizeof(QAP_MODULE_CMD_FLUSH), NULL, NULL, NULL);
ret = qap_module_cmd(qap_module_handle, QAP_MODULE_CMD_STOP, sizeof(QAP_MODULE_CMD_STOP), NULL, NULL, NULL);
fprintf(stdout, "Stopped feeding input %s : %p\n", stream_info->filename, fp_input);
ALOGV("Stopped feeding input %s : %p", stream_info->filename, fp_input);
break;
}
reply_data = (char*) calloc(1, 100);
is_buffer_available = 0;
temp_ptr = buffer->common_params.data;
int time_index = data_write_count;
if (kpi_mode) {
if (data_write_count > 5 && data_write_count < TIMESTAMP_ARRAY_SIZE) {
gettimeofday(&tcont_ts1, NULL);
data_input_ts_arr[data_write_count] = buffer->common_params.timestamp;
data_input_st_arr[data_write_count] = (tcont_ts1.tv_sec) * 1000 + (tcont_ts1.tv_usec) / 1000;
ALOGV("%s::%d Kpi cont ts1 %lf, buffer timestamp %ld count %d",
__func__, __LINE__, data_input_st_arr[data_write_count], data_input_ts_arr[data_write_count], data_write_count);
}
if (data_write_count < TIMESTAMP_ARRAY_SIZE)
data_write_count++;
}
do {
bytes_consumed = qap_module_process(qap_module_handle, buffer);
if (bytes_consumed > 0) {
buffer->common_params.data += bytes_consumed;
buffer->common_params.size -= bytes_consumed;
}
ALOGV("%s %d, %s feeding Input of size %d and bytes_cosumed is %d",
__FUNCTION__, __LINE__,stream_info->filename, bytes_read, bytes_consumed);
{
if (bytes_consumed < 0) {
pthread_mutex_lock(&stream_info->input_buffer_available_lock);
stream_info->input_buffer_available_size = 0;
pthread_mutex_unlock(&stream_info->input_buffer_available_lock);
while (buffer->common_params.size > stream_info->input_buffer_available_size) {
ALOGV("%s %d: %s waiting for input buffer availability.",
__FUNCTION__, __LINE__, stream_info->filename);
pthread_mutex_lock(&stream_info->input_buffer_available_lock);
pthread_cond_wait(&stream_info->input_buffer_available_cond,
&stream_info->input_buffer_available_lock);
pthread_mutex_unlock(&stream_info->input_buffer_available_lock);
ALOGV("%s %d: %s input buffer available, size %lu.",
__FUNCTION__, __LINE__,
stream_info->filename,
stream_info->input_buffer_available_size);
}
if(kpi_mode && time_index > 5) {
gettimeofday(&tcont_ts1, NULL);
data_input_st_arr[time_index] = (tcont_ts1.tv_sec) * 1000 + (tcont_ts1.tv_usec) / 1000;
}
}
}
} while (buffer->common_params.size > 0 && !stop_playback);
if (reply_data)
free(reply_data);
buffer->common_params.data = temp_ptr;
if (!(stream_info->system_input || stream_info->sec_input) && !(kpi_mode)) {
usleep(5000); //To swtich between main and secondary threads incase of dual input
}
} while (1);
wait_for_eos:
if (stream_info->sec_input) {
if (!(stream_info->flags & AUDIO_OUTPUT_FLAG_ASSOCIATED)) {
if (!main2_eos_received) {
pthread_mutex_lock(&main2_eos_lock);
pthread_cond_wait(&main2_eos_cond, &main2_eos_lock);
pthread_mutex_unlock(&main2_eos_lock);
}
main2_eos_received = false;
fprintf(stdout, "Received EOS event for main2 input\n");
ALOGV("Received EOS event for main2 input\n");
} else {
if (!sec_eos_received) {
pthread_mutex_lock(&sec_eos_lock);
pthread_cond_wait(&sec_eos_cond, &sec_eos_lock);
pthread_mutex_unlock(&sec_eos_lock);
}
sec_eos_received = false;
fprintf(stdout, "Received EOS event for secondary input\n");
ALOGV("Received EOS event for secondary input\n");
}
}
if (!(stream_info->system_input || stream_info->sec_input)){
if (!main_eos_received) {
pthread_mutex_lock(&main_eos_lock);
pthread_cond_wait(&main_eos_cond, &main_eos_lock);
pthread_mutex_unlock(&main_eos_lock);
}
main_eos_received = false;
fprintf(stdout, "Received EOS event for main input\n");
ALOGV("Received EOS event for main input\n");
}
exit:
if (NULL != buffer && NULL != buffer->common_params.data) {
free( buffer->common_params.data);
buffer->common_params.data = NULL;
free( buffer);
buffer = NULL;
}
qap_module_deinit(qap_module_handle);
if ((true == play_list) && (0 == play_list_cnt) && qap_out_hal_handle) {
ALOGV("%s %d QAP_CALLBACK_EVENT_EOS for play list received", __func__, __LINE__);
qap_out_hal_handle = NULL;
} else if (!play_list && qap_out_hal_handle) {
ALOGV("%s %d QAP_CALLBACK_EVENT_EOS received", __func__, __LINE__);
qap_out_hal_handle = NULL;
}
if (kpi_mode) {
qap_wrapper_measure_kpi_values(cold_start, cold_stop);
}
fprintf(stdout, "%s::%d , THREAD EXIT \n", __func__, __LINE__);
ALOGD("%s::%d , THREAD EXIT \n", __func__, __LINE__);
return NULL;
}
qap_module_handle_t qap_wrapper_stream_open(void* stream_data)
{
qap_module_config_t input_config = {0};
int ret = 0;
int i = 0;
stream_config *stream_info = (stream_config *)stream_data;
qap_module_handle_t qap_module_handle = NULL;
input_config.sample_rate = stream_info->config.sample_rate;
input_config.channels = stream_info->channels;
input_config.bit_width = stream_info->config.offload_info.bit_width;
if (stream_info->filetype == FILE_DTS)
stream_info->bytes_to_read = FRAME_SIZE;
else
stream_info->bytes_to_read = 1024;
input_streams_count++;
if (stream_info->filetype == FILE_WAV) {
switch (stream_info->flags)
{
case QAP_MODULE_FLAG_SYSTEM_SOUND:
ALOGV("%s::%d Set System Sound Flag", __func__, __LINE__);
break;
case QAP_MODULE_FLAG_APP_SOUND:
ALOGV("%s::%d Set System APP Flag", __func__, __LINE__);
break;
case QAP_MODULE_FLAG_OTT_SOUND:
ALOGV("%s::%d Set OTT Sound Flag", __func__, __LINE__);
break;
default:
ALOGE("%s::%d unsupported flag for PCM input.", __func__, __LINE__);
return NULL;
}
input_config.flags = stream_info->flags;
stream_info->system_input = true;
has_system_input = true;
} else {
if (input_streams_count > 1) {
if (stream_info->flags & AUDIO_OUTPUT_FLAG_ASSOCIATED) {
ALOGV("%s::%d Set Secondary Assoc Input Flag", __func__, __LINE__);
input_config.flags = QAP_MODULE_FLAG_SECONDARY;
stream_info->sec_input = true;
} else {
ALOGV("%s::%d Set Secondary Main Input Flag", __func__, __LINE__);
input_config.flags = QAP_MODULE_FLAG_PRIMARY;
stream_info->sec_input = true;
}
stream_info->bytes_to_read = 2048;
} else {
if (stream_info->flags & AUDIO_OUTPUT_FLAG_ASSOCIATED) {
ALOGV("%s::%d Set Secondary Assoc Input Flag", __func__, __LINE__);
input_config.flags = QAP_MODULE_FLAG_SECONDARY;
stream_info->sec_input = true;
} else {
ALOGV("%s::%d Set Primary Main Input Flag", __func__, __LINE__);
input_config.flags = QAP_MODULE_FLAG_PRIMARY;
}
}
}
if (!encode)
input_config.module_type = QAP_MODULE_DECODER;
else
input_config.module_type = QAP_MODULE_ENCODER;
ret = qap_wrapper_map_input_format(stream_info->config.offload_info.format, &input_config.format);
if (ret == -EINVAL)
return NULL;
ret = qap_module_init(qap_session_handle, &input_config, &qap_module_handle);
if (qap_module_handle == NULL) {
fprintf(stderr, "%s Module Handle is Null\n", __func__);
return NULL;
}
qap_module_set_callback(qap_module_handle, &qap_wrapper_module_callback, stream_info);
primary_stream_close = false;
stream_cnt++;
return qap_module_handle;
}
void get_play_list(FILE *fp, stream_config (*stream_param)[], int *num_of_streams, char *kvp_str[])
{
char *token = NULL;
char *strings[100] = {NULL};
char cmd_str[1024] = {0};
char *tmp_str = NULL;
int i = 0;
do {
int j = 0, cnt = 0, status = 0;
if (fgets(cmd_str, sizeof(cmd_str), fp) != NULL)
tmp_str = strdup(cmd_str);
else
break;
fprintf(stdout, "%s %d tmp_str is %s", __FUNCTION__, __LINE__, tmp_str);
token = strtok(tmp_str, " ");
if (NULL != token) {
strings[cnt++] = strdup("playlist");
strings[cnt++] = strdup(token);
while (NULL != (token = strtok(NULL, " "))) {
strings[cnt] = strdup(token);
ALOGV("%s %d strings[%d] is %s", __FUNCTION__, __LINE__, cnt, strings[cnt]);
cnt++;
}
for (j = 0;j< cnt;j++) {
if (!strncmp(strings[j], "-f", 2)) {
(*stream_param)[i].filename = strdup(strings[j+1]);
} else if (!strncmp(strings[j], "-r", 2)) {
(*stream_param)[i].config.offload_info.sample_rate = atoi(strings[j+1]);
(*stream_param)[i].config.sample_rate = atoi(strings[j+1]);
} else if (!strncmp(strings[j], "-c", 2)) {
(*stream_param)[i].channels = atoi(strings[j+1]);
(*stream_param)[i].config.channel_mask = audio_channel_out_mask_from_count(atoi(strings[j+1]));
} else if (!strncmp(strings[j], "-b", 2)) {
(*stream_param)[i].config.offload_info.bit_width = atoi(strings[j+1]);
} else if (!strncmp(strings[j], "-d", 2)) {
(*stream_param)[i].output_device = atoll(strings[j+1]);
} else if (!strncmp(strings[j], "-t", 2)) {
(*stream_param)[i].filetype = atoi(strings[j+1]);
} else if (!strncmp(strings[j], "-a", 2)) {
(*stream_param)[i].aac_fmt_type = atoi(strings[j+1]);
}
}
free(tmp_str);
tmp_str = NULL;
}
if(NULL != (*stream_param)[i].filename) {
*num_of_streams = i+1;
play_list = true;
kvp_str[i] = (char *)qap_wrapper_get_cmd_string_from_arg_array(cnt, strings, &status);
ALOGV("%s %d kvp_str[%d] is %s", __FUNCTION__, __LINE__, i, kvp_str[i]);
}
for (j=0; j < cnt; j++) {
if (NULL != strings[j]){
free(strings[j]);
strings[j] = NULL;
}
}
i++;
}while(NULL != cmd_str);
return;
}
void hal_test_qap_usage() {
printf(" \n qap commands \n");
printf(" -qap - Enabling playback through QAP for nun tunnel decoding mode\n");
printf(" -bd - Enabling Broadcast Decode/Encode session through QAP\n");
printf(" -broadcast - Enabling playback through QAP for nun tunnel decoding mode\n");
printf(" -y --timestamp filename - Input timestamp file to be used to send timestamp and bytes to be read from main input file.\n");
printf(" -z --framesize filename - Input framesize file to be used to send bytes to be read from main input file.\n");
printf(" hal_play_test -qap -broadcast -f /data/5ch_dd_25fps_channeld_id.ac3 -t 9 -d 2 -v 0.01 -r 48000 -c 6 \n");
printf(" -> plays AC3 stream(-t = 9) on speaker device(-d = 2)\n");
printf(" -> 6 channels and 48000 sample rate\n\n");
printf(" -> using QAP with Broadcast session\n\n");
printf(" hal_play_test -qap -bd -f /data/200_48_16_ieq_mix_voice_40s.ec3 -t 11 -d 2 -v 0.01 -r 48000 -c 2 \n");
printf(" -> plays EAC3 stream(-t = 11) on speaker device(-d = 2)\n");
printf(" -> 2 channels and 48000 sample rate\n\n");
printf(" -> using QAP with Bluray session\n\n");
}