hal_play_test : Support for Playback through QAP

Add support for Playback of Dolby and DTS formats through QAP
Add KPI support, add support to disable dump.

Depends-on: 2002598
Change-Id: If29faaeca545ce7809008f747f1d04807b105e9a
diff --git a/configure.ac b/configure.ac
index da39527..978d235 100644
--- a/configure.ac
+++ b/configure.ac
@@ -114,6 +114,7 @@
 AM_CONDITIONAL([AUDIO_HW_LOOPBACK], [test x$AUDIO_FEATURE_ENABLED_AUDIO_HW_LOOPBACK = xtrue])
 AM_CONDITIONAL([AUDIO_PARSER], [test x$AUDIO_FEATURE_ENABLED_PARSER = xtrue])
 AM_CONDITIONAL([DTSHD_PARSER], [test x$AUDIO_FEATURE_ENABLED_DTSHD_PARSER = xtrue])
+AM_CONDITIONAL([QAP], [test x$AUDIO_FEATURE_ENABLED_QAP = xtrue])
 
 AC_CONFIG_FILES([ \
         Makefile \
diff --git a/qahw_api/test/Makefile.am b/qahw_api/test/Makefile.am
index d87962b..b4bbea7 100644
--- a/qahw_api/test/Makefile.am
+++ b/qahw_api/test/Makefile.am
@@ -6,9 +6,19 @@
 
 hal_play_test_SOURCES = qahw_playback_test.c \
                         qahw_effect_test.c
-hal_play_test_CPPFLAGS = $(PLAY_CPPFLAGS) $(PLAY_INCLUDES)
+
 hal_play_test_LDADD = -lutils ../libqahw.la
 
+if QAP
+AM_CFLAGS = -DQAP
+AM_CFLAGS += -I ${WORKSPACE}/audio/mm-audio/qap_wrapper/inc/
+hal_play_test_SOURCES += qap_wrapper_extn.c
+hal_play_test_LDADD += -lqap_wrapper
+endif
+
+hal_play_test_CPPFLAGS = $(PLAY_CPPFLAGS) $(PLAY_INCLUDES)
+hal_play_test_CFLAGS = $(AM_CFLAGS)
+hal_play_test_CFLAGS = -DLINUX_ENABLED
 
 bin_PROGRAMS += hal_rec_test
 
@@ -18,6 +28,7 @@
 hal_rec_test_SOURCES = qahw_multi_record_test.c
 hal_rec_test_CPPFLAGS = -Dstrlcat=g_strlcat $(GLIB_CFLAGS) -include glib.h
 hal_rec_test_CPPFLAGS += $(REC_CPPFLAGS) $(REC_INCLUDES)
+hal_play_test_CFLAGS += $(AM_CFLAGS)
 hal_rec_test_LDADD = -lutils ../libqahw.la $(GLIB_LIBS)
 
 bin_PROGRAMS += trans_loopback_test
diff --git a/qahw_api/test/qahw_playback_test.c b/qahw_api/test/qahw_playback_test.c
index c27f920..2ead153 100644
--- a/qahw_api/test/qahw_playback_test.c
+++ b/qahw_api/test/qahw_playback_test.c
@@ -18,22 +18,7 @@
 
 /* Test app to play audio at the HAL layer */
 
-#include <getopt.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <time.h>
-#include <signal.h>
-#include <cutils/str_parms.h>
-#include <tinyalsa/asoundlib.h>
-#include "qahw_api.h"
-#include "qahw_defs.h"
-#include "qahw_effect_api.h"
-#include "qahw_effect_test.h"
+#include "qahw_playback_test.h"
 
 #define nullptr NULL
 
@@ -69,50 +54,10 @@
 #define DTSHD_CHUNK_STREAM_KEYWORD "STRMDATA"
 #define DTSHD_META_KEYWORD_SIZE 8 /*in bytes */
 
-static int get_wav_header_length (FILE* file_stream);
 static ssize_t get_bytes_to_read(FILE* file, int filetype);
 static void init_streams(void);
 int pthread_cancel(pthread_t thread);
 
-
-enum {
-    FILE_WAV = 1,
-    FILE_MP3,
-    FILE_AAC,
-    FILE_AAC_ADTS,
-    FILE_FLAC,
-    FILE_ALAC,
-    FILE_VORBIS,
-    FILE_WMA,
-    FILE_AC3,
-    FILE_AAC_LATM,
-    FILE_EAC3,
-    FILE_EAC3_JOC,
-    FILE_DTS,
-    FILE_MP2,
-    FILE_APTX,
-    FILE_TRUEHD,
-    FILE_IEC61937
-};
-
-typedef enum {
-    USB_MODE_DEVICE,
-    USB_MODE_HOST,
-    USB_MODE_NONE
-} usb_mode_type_t;
-
-typedef enum {
-    AAC_LC = 1,
-    AAC_HE_V1,
-    AAC_HE_V2
-} aac_format_type_t;
-
-typedef enum {
-    WMA = 1,
-    WMA_PRO,
-    WMA_LOSSLESS
-} wma_format_type_t;
-
 struct wav_header {
     uint32_t riff_id;
     uint32_t riff_sz;
@@ -129,18 +74,6 @@
     uint32_t data_sz;
 };
 
-struct audio_config_params {
-    qahw_module_handle_t *qahw_mod_handle;
-    audio_io_handle_t handle;
-    audio_devices_t input_device;
-    audio_config_t config;
-    audio_input_flags_t flags;
-    const char* kStreamName ;
-    audio_source_t kInputSource;
-    char *file_name;
-    volatile bool thread_exit;
-};
-
 struct proxy_data {
     struct audio_config_params acp;
     struct wav_header hdr;
@@ -162,42 +95,6 @@
     uint32_t config_mask;
 };
 
-typedef struct {
-    qahw_module_handle_t *qahw_in_hal_handle;
-    qahw_module_handle_t *qahw_out_hal_handle;
-    audio_io_handle_t handle;
-    char* filename;
-    FILE* file_stream;
-    int filetype;
-    int stream_index;
-    audio_devices_t output_device;
-    audio_devices_t input_device;
-    audio_config_t config;
-    audio_output_flags_t flags;
-    qahw_stream_handle_t* out_handle;
-    qahw_stream_handle_t* in_handle;
-    int channels;
-    aac_format_type_t aac_fmt_type;
-    wma_format_type_t wma_fmt_type;
-    char *kvpair_values;
-    bool flags_set;
-    usb_mode_type_t usb_mode;
-    int effect_index;
-    int effect_preset_strength;
-    bool drift_query;
-    bool drift_correction;
-    bool play_later;
-    char *device_url;
-    thread_func_t ethread_func;
-    thread_data_t *ethread_data;
-    cmd_data_t cmd_data;
-    pthread_cond_t write_cond;
-    pthread_mutex_t write_lock;
-    pthread_cond_t drain_cond;
-    pthread_mutex_t drain_lock;
-    bool interactive_strm;
-}stream_config;
-
 /* Lock for dual main usecase */
 pthread_cond_t dual_main_cond;
 pthread_mutex_t dual_main_lock;
@@ -211,13 +108,12 @@
 FILE * log_file = NULL;
 volatile bool stop_playback = false;
 const char *log_filename = NULL;
-float vol_level = 0.01;
 struct proxy_data proxy_params;
 pthread_t playback_thread[MAX_PLAYBACK_STREAMS];
 bool thread_active[MAX_PLAYBACK_STREAMS] = { false };
+bool qap_wrapper_session_active = false;
 
 stream_config stream_param[MAX_PLAYBACK_STREAMS];
-bool kpi_mode;
 bool event_trigger;
 
 /*
@@ -1000,6 +896,7 @@
     case AAC_LC:
     case AAC_HE_V1:
     case AAC_HE_V2:
+    case AAC_LOAS:
         valid_format_type = true;
         break;
     default:
@@ -1171,6 +1068,7 @@
            fprintf(log_file, "Does not support given filetype\n");
            fprintf(stderr, "Does not support given filetype\n");
            usage();
+           hal_test_qap_usage();
            return;
     }
     stream_info->config.sample_rate = stream_info->config.offload_info.sample_rate;
@@ -1608,10 +1506,10 @@
     printf(" -m  --mode                                - usb operating mode(Device Mode is default)\n");
     printf("                                             0:Device Mode(host drives the stream and its params and so no need to give params as input)\n");
     printf("                                             1:Host Mode(user can give stream and stream params via a stream(SD card file) or setup loopback with given params\n");
-    printf(" -O  --output-ch-map                       - output channel map");
-    printf(" -I  --input-ch-map                        - input channel map");
-    printf(" -M  --mixer-coeffs                        - mixer coefficient matrix");
-    printf(" -i  --intr-strm                           - interactive stream indicator");
+    printf(" -O  --output-ch-map                       - output channel map\n");
+    printf(" -I  --input-ch-map                        - input channel map\n");
+    printf(" -M  --mixer-coeffs                        - mixer coefficient matrix\n");
+    printf(" -i  --intr-strm                           - interactive stream indicator\n");
     printf(" -C  --Device Config                       - Device Configuration params\n");
     printf("                                             Params should be in the order defined in struct qahw_device_cfg_param. Order is: \n");
     printf("                                             <sample_rate>, <channels>, <bit_width>, <format>, <device>, <channel_map[channels]>, <channel_allocation> \n");
@@ -1683,7 +1581,7 @@
     printf("                                          ->Note:all the USB device commmands(above) should be accompanied with the host side commands\n\n");
 }
 
-static int get_wav_header_length (FILE* file_stream)
+int get_wav_header_length (FILE* file_stream)
 {
     int subchunk_size = 0, wav_header_len = 0;
 
@@ -1800,7 +1698,7 @@
      return file_read_size;
 }
 
-static qahw_module_handle_t * load_hal(audio_devices_t dev) {
+qahw_module_handle_t * load_hal(audio_devices_t dev) {
     qahw_module_handle_t *hal = NULL;
 
     if ((AUDIO_DEVICE_IN_USB_DEVICE == dev) ||
@@ -1844,7 +1742,7 @@
  * this function unloads all the loaded hal modules so this should be called
  * after all the stream playback are concluded.
  */
-static int unload_hals() {
+int unload_hals() {
 
     if (usb_hal_handle) {
         fprintf(log_file,"\nUnLoading usb HAL\n");
@@ -1994,8 +1892,54 @@
         token_string = NULL;
     } else
         return -EINVAL;
+}
+
+#ifdef QAP
+int start_playback_through_qap(char * kvp_string, int num_of_streams) {
+    stream_config *stream = NULL;
+    int rc = 0;
+    int i;
+
+    fprintf(stdout, "kvp_string %s and num_of_streams %d\n", kvp_string, num_of_streams);
+    for (i = 0; i < num_of_streams; i++) {
+        stream = &stream_param[i];
+        if (stream->filename) {
+            if ((stream->file_stream = fopen(stream->filename, "r"))== NULL) {
+                fprintf(log_file, "Cannot open audio file %s\n", stream->filename);
+                fprintf(stderr, "Cannot open audio file %s\n", stream->filename);
+                return -EINVAL;
+            }
+        }
+        get_file_format(stream);
+        fprintf(stdout, "Playing from:%s\n", stream->filename);
+        qap_module_handle_t qap_module_handle = NULL;
+        if (!qap_wrapper_session_active) {
+            rc = qap_wrapper_session_open(kvp_string, stream, num_of_streams);
+            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);
+                rc = pthread_create(&playback_thread[i], NULL, qap_wrapper_start_stream, (void *)&stream_param[i]);
+                if (rc) {
+                    fprintf(stderr, "stream %d: failed to create thread\n", stream->stream_index);
+                    return -EINVAL;
+                }
+                thread_active[i] = true;
+            }
+        }
+    }
     return 0;
 }
+#endif
 
 int main(int argc, char* argv[]) {
     char *ba = NULL;
@@ -2028,6 +1972,7 @@
     init_streams();
 
     int num_of_streams = 1;
+    char kvp_string[KV_PAIR_MAX_LENGTH] = {0};
 
     struct option long_options[] = {
         /* These options set a flag. */
@@ -2038,6 +1983,7 @@
         {"channels",      required_argument,    0, 'c'},
         {"bitwidth",      required_argument,    0, 'b'},
         {"volume",        required_argument,    0, 'v'},
+        {"enable-dump",   required_argument,    0, 'V'},
         {"log-file",      required_argument,    0, 'l'},
         {"dump-file",     required_argument,    0, 'D'},
         {"file-type",     required_argument,    0, 't'},
@@ -2056,13 +2002,18 @@
         {"mode",          required_argument,    0, 'm'},
         {"effect-preset",   required_argument,    0, 'p'},
         {"effect-strength", required_argument,    0, 'S'},
-        {"device-config", required_argument,    0, 'C'},
-        {"help",          no_argument,          0, 'h'},
+#ifdef QAP
+        {"render-format", required_argument,    0, 'x'},
+        {"timestamp-file", required_argument,    0, 'y'},
+        {"framesize-file", required_argument,    0, 'z'},
+#endif
         {"output-ch-map", required_argument,    0, 'O'},
         {"input-ch-map",  required_argument,    0, 'I'},
         {"mixer-coeffs",  required_argument,    0, 'M'},
         {"num-out-ch",    required_argument,    0, 'o'},
         {"intr-strm",    required_argument,    0, 'i'},
+        {"device-config", required_argument,    0, 'C'},
+        {"help",          no_argument,          0, 'h'},
         {0, 0, 0, 0}
     };
 
@@ -2085,7 +2036,11 @@
 
     while ((opt = getopt_long(argc,
                               argv,
-                              "-f:r:c:b:d:s:v:l:t:a:w:k:PD:KF:Ee:A:u:m:S:C:p:qQhI:O:M:o:i:",
+#ifdef QAP
+                              "-f:r:c:b:d:s:v:V:l:t:a:w:k:PD:KF:Ee:A:u:m:S:C:p::x:y:z:qQhI:O:M:o:i:h:",
+#else
+                              "-f:r:c:b:d:s:v:V:l:t:a:w:k:PD:KF:Ee:A:u:m:S:C:p:qQhI:O:M:o:i:h:",
+#endif
                               long_options,
                               &option_index)) != -1) {
 
@@ -2116,6 +2071,9 @@
         case 'v':
             vol_level = atof(optarg);
             break;
+        case 'V':
+            enable_dump = atof(optarg);
+            break;
         case 'l':
             log_filename = optarg;
             if (strcasecmp(log_filename, "stdout") &&
@@ -2220,6 +2178,19 @@
             break;
         case 'o':
             mm_params.num_output_channels = atoi(optarg);
+            break;
+#ifdef QAP
+        case 'x':
+            render_format = atoi(optarg);
+            break;
+        case 'y':
+            stream_param[i].timestamp_filename = optarg;
+            break;
+        case 'z':
+            stream_param[i].framesize_filename = optarg;
+            fprintf(stderr, "file name is %s\n", stream_param[i].framesize_filename);
+            break;
+#endif
         case 'C':
             fprintf(log_file, " In Device config \n");
             fprintf(stderr, " In Device config \n");
@@ -2283,6 +2254,9 @@
             break;
         case 'h':
             usage();
+#ifdef QAP
+            hal_test_qap_usage();
+#endif
             return 0;
             break;
 
@@ -2373,20 +2347,27 @@
 
     }
 
+    if (is_qap_session_active(argc, argv, kvp_string)) {
+        rc = start_playback_through_qap(kvp_string, num_of_streams);
+        if (rc != 0) {
+            fprintf(stderr, "QAP playback failed\n");
+        }
+        goto exit;
+    }
     for (i = 0; i < num_of_streams; i++) {
         stream = &stream_param[i];
 
         if ((kpi_mode == false) &&
             (AUDIO_DEVICE_NONE == stream->input_device)){
-            if (stream_param[PRIMARY_STREAM_INDEX].filename == nullptr) {
-                fprintf(log_file, "Primary file name is must for non kpi-mode\n");
-                fprintf(stderr, "Primary file name is must for non kpi-mode\n");
-                goto exit;
-            }
+                if (stream_param[PRIMARY_STREAM_INDEX].filename == nullptr) {
+                    fprintf(log_file, "Primary file name is must for non kpi-mode\n");
+                    fprintf(stderr, "Primary file name is must for non kpi-mode\n");
+                    goto exit;
+                }
         }
 
         if (stream->output_device != AUDIO_DEVICE_NONE)
-            if ((stream->qahw_out_hal_handle = load_hal(stream->output_device)) <= 0)
+             if ((stream->qahw_out_hal_handle = load_hal(stream->output_device)) <= 0)
                 goto exit;
 
         if (stream->input_device != AUDIO_DEVICE_NONE)
@@ -2397,8 +2378,8 @@
             (AUDIO_DEVICE_NONE != stream->input_device))
             /*
              * hal loopback at what params we need to probably detect.
-             */
-             if(detect_stream_params(stream) < 0)
+            */
+            if(detect_stream_params(stream) < 0)
                 goto exit;
 
         if (stream->filename) {
@@ -2524,13 +2505,17 @@
                 fprintf(log_file, "QAHW_PARAM_CH_MIX_MATRIX_PARAMS could not be sent!\n");
             }
         }
+
     }
 
 exit:
-
     for (i=0; i<MAX_PLAYBACK_STREAMS; i++) {
         if(thread_active[i])
-            pthread_join(playback_thread[i], NULL);
+           pthread_join(playback_thread[i], NULL);
+    }
+
+    if(qap_wrapper_session_active) {
+        qap_wrapper_session_close();
     }
 
     /*
diff --git a/qahw_api/test/qahw_playback_test.h b/qahw_api/test/qahw_playback_test.h
new file mode 100644
index 0000000..faf32ef
--- /dev/null
+++ b/qahw_api/test/qahw_playback_test.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2016-2017, 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.
+ */
+
+#ifndef QAHW_PLAYBACK_TEST_H
+#define QAHW_PLAYBACK_TEST_H
+
+#include <getopt.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <signal.h>
+#include <cutils/str_parms.h>
+#include <tinyalsa/asoundlib.h>
+#include "qahw_api.h"
+#include "qahw_defs.h"
+#include "qahw_effect_api.h"
+#include "qahw_effect_test.h"
+
+#define MAX_STR_LEN 256
+typedef void* qap_module_handle_t;
+bool kpi_mode;
+bool enable_dump;
+float vol_level;
+uint8_t render_format;
+
+
+enum {
+    FILE_WAV = 1,
+    FILE_MP3,
+    FILE_AAC,
+    FILE_AAC_ADTS,
+    FILE_FLAC,
+    FILE_ALAC,
+    FILE_VORBIS,
+    FILE_WMA,
+    FILE_AC3,
+    FILE_AAC_LATM,
+    FILE_EAC3,
+    FILE_EAC3_JOC,
+    FILE_DTS,
+    FILE_MP2,
+    FILE_APTX,
+    FILE_TRUEHD,
+    FILE_IEC61937
+};
+
+typedef enum {
+    USB_MODE_DEVICE,
+    USB_MODE_HOST,
+    USB_MODE_NONE
+} usb_mode_type_t;
+
+typedef enum {
+    AAC_LC = 1,
+    AAC_HE_V1,
+    AAC_HE_V2,
+    AAC_LOAS
+} aac_format_type_t;
+
+typedef enum {
+    WMA = 1,
+    WMA_PRO,
+    WMA_LOSSLESS
+} wma_format_type_t;
+
+struct audio_config_params {
+    qahw_module_handle_t *qahw_mod_handle;
+    audio_io_handle_t handle;
+    audio_devices_t input_device;
+    audio_config_t config;
+    audio_input_flags_t flags;
+    const char* kStreamName ;
+    audio_source_t kInputSource;
+    char *file_name;
+    volatile bool thread_exit;
+};
+
+typedef struct {
+    qahw_module_handle_t *qahw_in_hal_handle;
+    qahw_module_handle_t *qahw_out_hal_handle;
+    audio_io_handle_t handle;
+    char* filename;
+    FILE* file_stream;
+    char* timestamp_filename;
+    FILE* timestamp_file_ptr;
+    char* framesize_filename;
+    FILE* framesize_file_ptr;
+    int filetype;
+    int stream_index;
+    audio_devices_t output_device;
+    audio_devices_t input_device;
+    audio_config_t config;
+    audio_output_flags_t flags;
+    qahw_stream_handle_t* out_handle;
+    qahw_stream_handle_t* in_handle;
+    int channels;
+    aac_format_type_t aac_fmt_type;
+    wma_format_type_t wma_fmt_type;
+    char *kvpair_values;
+    bool flags_set;
+    usb_mode_type_t usb_mode;
+    int effect_index;
+    int effect_preset_strength;
+    bool drift_query;
+    bool drift_correction;
+    bool play_later;
+    char *device_url;
+    thread_func_t ethread_func;
+    thread_data_t *ethread_data;
+    cmd_data_t cmd_data;
+    int bytes_to_read;
+    qap_module_handle_t qap_module_handle;
+    bool sec_input;
+    bool system_input;
+    pthread_cond_t write_cond;
+    pthread_mutex_t write_lock;
+    pthread_cond_t drain_cond;
+    pthread_mutex_t drain_lock;
+    bool interactive_strm;
+}stream_config;
+
+
+qahw_module_handle_t * load_hal(audio_devices_t dev);
+int unload_hals();
+int get_wav_header_length (FILE* file_stream);
+
+#ifndef QAP
+#define hal_test_qap_usage()                                             (0)
+#define qap_wrapper_get_single_kvp(key, kv_pairs, status)                (0)
+#define qap_wrapper_session_open(kv_pairs, stream_data, num_of_streams)  (0)
+#define qap_wrapper_session_close()                                      (0)
+#define qap_wrapper_stream_open(stream_data)                             (0)
+#define qap_wrapper_get_cmd_string_from_arg_array(argc, argv, status)    (0)
+#define qap_wrapper_start_stream (stream_data)                           (0)
+#define is_qap_session_active(argc, argv, kvp_string)                    (0)
+#define start_playback_through_qap(kvp_string, num_of_streams)           (0)
+#else
+void hal_test_qap_usage();
+char * qap_wrapper_get_single_kvp(const char *key, const char *kv_pairs, int *status);
+int qap_wrapper_session_open(char *kv_pairs, void* stream_data, int num_of_streams);
+int qap_wrapper_session_close();
+qap_module_handle_t qap_wrapper_stream_open(void* stream_data);
+char * qap_wrapper_get_cmd_string_from_arg_array(int argc, char * argv[], int *status);
+void *qap_wrapper_start_stream (void* stream_data);
+bool is_qap_session_active(int argc, char* argv[], char *kvp_string);
+int start_playback_through_qap(char * kvp_string, int num_of_streams);
+#endif
+#endif /* QAHW_PLAYBACK_TEST_H */
diff --git a/qahw_api/test/qap_wrapper_extn.c b/qahw_api/test/qap_wrapper_extn.c
new file mode 100644
index 0000000..58580dc
--- /dev/null
+++ b/qahw_api/test/qap_wrapper_extn.c
@@ -0,0 +1,1244 @@
+/*
+ * Copyright (c) 2016-2017, 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/log.h>
+#include <cutils/str_parms.h>
+#include <system/audio.h>
+#include <qap_api.h>
+#include <qti_audio.h>
+#include "qahw_playback_test.h"
+
+#undef LOG_TAG
+#define LOG_TAG "HAL_TEST"
+#undef LOG_NDEBUG
+/*#define LOG_NDEBUG 0*/
+
+#if LINUX_ENABLED
+#define QAC_LIB_MS12 "/usr/lib/libdolby_ms12_wrapper.so"
+#define QAC_LIB_M8   "/usr/lib/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 2048*2
+#define MAX_BUFFER_SIZE 13000
+#define CONTIGUOUS_TIMESTAMP 0x7fffffff
+
+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_mch_handle = 0x998;
+audio_io_handle_t qap_stream_out_hp_handle = 0x997;
+
+FILE *fp_output_writer_spk = NULL;
+FILE *fp_output_writer_hp = NULL;
+FILE *fp_output_writer_mch = NULL;
+FILE *fp_output_timestamp_file = 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 dts_formats = false;
+bool timestamp_mode = false;
+int  data_write_count = 0;
+int data_callback_count = 0;
+
+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;
+
+qap_session_outputs_config_t session_output_config;
+bool session_output_configured = false;
+clock_t tcold_start, tcold_stop;
+clock_t tcont_start, tcont_stop;
+bool has_system_input = false;
+char session_kv_pairs[256] = {0};
+
+static void qap_wrapper_measure_kpi_values(clock_t tcold_start, clock_t tcold_stop,
+                                           clock_t tcont_start, clock_t tcont_stop)
+{
+    double cold_time_latency, cont_time_latency;
+    cold_time_latency = ((double)(tcold_stop - tcold_start))/CLOCKS_PER_SEC;
+    cont_time_latency = ((double)(tcont_stop - tcont_start))/CLOCKS_PER_SEC;
+    fprintf(stdout, "cold time latency %lf ms and cont time latency %lf ms\n", cold_time_latency*1000, cont_time_latency*1000);
+}
+
+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];
+        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);
+                }
+            }
+        }
+    }
+}
+
+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;
+}
+
+#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 = malloc((strlen(token) + 1) * sizeof(char));
+                memset(kvp, 0, strlen(token) + 1);
+                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 = malloc((strlen(token) + 1) * sizeof(char));
+                        memset(kvp, 0, strlen(token) + 1);
+                        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 = malloc((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 = malloc(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;
+    }
+}
+
+void qap_wrapper_session_callback(qap_session_handle_t session_handle __unused, void* priv_data __unused, qap_callback_event_t event_id, int size __unused, 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);/*Need to add Main and Associated Flags during mixing case*/
+    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__);
+            pthread_mutex_lock(&main_eos_lock);
+            pthread_cond_signal(&main_eos_cond);
+            pthread_mutex_unlock(&main_eos_lock);
+
+            close_output_streams();
+            if (qap_out_hal_handle) {
+                unload_hals();
+                qap_out_hal_handle = NULL;
+            }
+            break;
+        case QAP_CALLBACK_EVENT_EOS_ASSOC:
+        case QAP_CALLBACK_EVENT_MAIN_2_EOS:
+            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);
+                pthread_mutex_unlock(&sec_eos_lock);
+            }
+            break;
+        case QAP_CALLBACK_EVENT_ERROR:
+            break;
+        case QAP_CALLBACK_EVENT_SUCCESS:
+            break;
+        case QAP_CALLBACK_EVENT_METADATA:
+        case QAP_CALLBACK_EVENT_OUTPUT_CFG_CHANGE:
+            break;
+        case QAP_CALLBACK_EVENT_DATA:
+            if (data != NULL) {
+                if (kpi_mode) {
+                    data_callback_count++;
+                    if (data_callback_count == 1) {
+                        tcold_stop = clock();
+                    } else if (data_callback_count == 15) {
+                        tcont_stop = clock();
+                        qap_wrapper_measure_kpi_values(tcold_start, tcold_stop, tcont_start, tcont_stop);
+                    }
+                }
+                qap_audio_buffer_t *buffer = (qap_audio_buffer_t *) data;
+                if (qap_out_hal_handle == NULL) {
+                    fprintf(stdout, "%s::%d: device id %d\n",__func__, __LINE__, buffer->buffer_parms.output_buf_params.output_id);
+                    qap_out_hal_handle = load_hal(buffer->buffer_parms.output_buf_params.output_id);
+                    if (qap_out_hal_handle == NULL) {
+                        fprintf(stderr, "Failed log load HAL\n");
+                        return;
+                    }
+                }
+
+                if (buffer && timestamp_mode) {
+                    char ch[100] = {0};
+                    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) {
+                    if (buffer->buffer_parms.output_buf_params.output_id &
+                            AUDIO_DEVICE_OUT_HDMI) {
+                        if (enable_dump && fp_output_writer_mch == NULL) {
+                            fp_output_writer_mch =
+                                         fopen("/sdcard/output_hdmi.dump","wb");
+                            if (fp_output_writer_mch) {
+                                fprintf(stdout, "output file :: "
+                                      "/sdcard/output_hdmi.dump"
+                                      " has been generated.\n");
+                            } else {
+                                fprintf(stderr, "Failed open hdmi dump file\n");
+                            }
+                        }
+                        if (fp_output_writer_mch) {
+                            ret = fwrite((unsigned char *)buffer->common_params.data, sizeof(unsigned char),
+                                          buffer->common_params.size, fp_output_writer_mch);
+                            fflush(fp_output_writer_mch);
+                        }
+                        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 (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 =
+                                                        session_output_config.output_config->sample_rate;
+                            if (session_output_config.output_config->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->channels == 2) {
+                                config.offload_info.channel_mask = config.channel_mask =
+                                    AUDIO_CHANNEL_OUT_STEREO;
+                            } else {
+                                config.offload_info.channel_mask = config.channel_mask =
+                                    audio_channel_out_mask_from_count(MAX_OUTPUT_CHANNELS);
+                            }
+                            devices = AUDIO_DEVICE_OUT_HDMI;
+
+                            ret = qahw_open_output_stream(qap_out_hal_handle, qap_stream_out_mch_handle, devices,
+                                 flags, &config, &qap_out_hdmi_handle, "stream");
+
+                            if (ret) {
+                                fprintf(stdout, "%s:%d could not open output stream, error - %d \n", __func__, __LINE__, ret);
+                                return;
+                            }
+                            ret = qahw_out_set_volume(qap_out_hdmi_handle, vol_level, vol_level);
+                            if (ret < 0)
+                                fprintf(stderr, "unable to set volume\n");
+                        }
+                        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) {
+                                    fprintf(stderr, "%s::%d write failed in hal\n", __func__, __LINE__);
+                                }
+                        }
+                    }
+                    if (buffer->buffer_parms.output_buf_params.output_id & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
+                        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 (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 =
+                                                        session_output_config.output_config->sample_rate;
+                            if (session_output_config.output_config->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;
+                            }
+
+                            config.offload_info.channel_mask = config.channel_mask =
+                                    AUDIO_CHANNEL_OUT_STEREO;
+                            devices = AUDIO_DEVICE_OUT_LINE;//ToDO - Need to change to AUDIO_DEVICE_OUT_WIRED_HEADPHONE
+
+                            ret = qahw_open_output_stream(qap_out_hal_handle, qap_stream_out_hp_handle, devices,
+                                 flags, &config, &qap_out_hp_handle, "stream");
+
+                            if (ret) {
+                                fprintf(stderr, "%s:%d could not open output stream, error - %d \n", __func__, __LINE__, ret);
+                                return;
+                            }
+                            ret = qahw_out_set_volume(qap_out_hp_handle, vol_level, vol_level);
+                            if (ret < 0)
+                                 fprintf(stderr, "unable to set volume\n");
+                        }
+                        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) {
+                                    fprintf(stderr, "%s::%d write failed in hal\n", __func__, __LINE__);
+                                }
+                        }
+                    }
+                    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 (!dts_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 (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 =
+                                                        session_output_config.output_config->sample_rate;
+                            if (session_output_config.output_config->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;
+                            }
+
+                            config.offload_info.channel_mask = config.channel_mask =
+                                    AUDIO_CHANNEL_OUT_STEREO;
+                            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;
+                            }
+                            fprintf(stderr, "%s::%d: open output for device %d\n", __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) {
+                                fprintf(stderr, "%s:%d could not open output stream, error - %d \n", __func__, __LINE__, ret);
+                                return;
+                            }
+                            ret = qahw_out_set_volume(qap_out_spk_handle, vol_level, vol_level);
+                            if (ret < 0)
+                                 fprintf(stderr, "unable to set volume\n");
+                        }
+                        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) {
+                                    fprintf(stderr, "%s::%d write failed in hal\n", __func__, __LINE__);
+                                }
+                        }
+                    }
+                }
+            }
+            break;
+        default:
+            break;
+    }
+}
+
+static void qap_wrapper_is_dap_enabled(char *kv_pairs, int out_device_id) {
+    int status = 0;
+    int temp = 0;
+    char *dap_kvp = NULL;
+    int *dap_value = NULL;
+    int dap_enable = 0;
+
+    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) {
+                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;
+                }
+            } else if ((out_device_id == AUDIO_DEVICE_OUT_LINE)||
+                       (out_device_id == 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;
+                }
+            }
+        }
+        free(dap_kvp);
+        dap_kvp = NULL;
+    }
+}
+
+int qap_wrapper_session_open(char *kv_pairs, void* stream_data, int num_of_streams)
+{
+    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;
+    uint8_t session_type = SESSION_BLURAY;
+
+    tcold_start = clock();
+    memset(&session_output_config, 0, sizeof(session_output_config));
+    strcpy(session_kv_pairs, kv_pairs);
+
+    session_type_kvp = qap_wrapper_get_single_kvp("broadcast", kv_pairs, &status);
+    if (session_type_kvp != NULL) {
+        session_type = SESSION_BROADCAST;
+        fprintf(stdout, "Session Type is Broadcast\n");
+        free(session_type_kvp);
+        session_type_kvp = NULL;
+    } else {
+        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 (num_of_streams > 1) {
+            fprintf(stderr, "Please specifiy proper session type\n");
+            return -EINVAL;
+        }
+    }
+
+    if (stream->filetype == FILE_DTS) {
+        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");
+        dts_formats = true;
+    } 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)) {
+        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;
+    }
+
+    qap_wrapper_is_dap_enabled(kv_pairs, stream->output_device);
+
+    encode_kvp = qap_wrapper_get_single_kvp("od", kv_pairs, &status);
+    if (encode_kvp != NULL) {
+        encode = true;
+        free(encode_kvp);
+        encode_kvp = NULL;
+    }
+
+    encode_kvp = qap_wrapper_get_single_kvp("odp", kv_pairs, &status);
+    if (encode_kvp != NULL) {
+        encode = true;
+        free(encode_kvp);
+        encode_kvp = NULL;
+    }
+
+    encode_kvp = qap_wrapper_get_single_kvp("odts", kv_pairs, &status);
+    if (encode_kvp != NULL) {
+        encode = true;
+        free(encode_kvp);
+        encode_kvp = NULL;
+    }
+
+    if (stream->filetype == FILE_DTS)
+        session_output_config.output_config->bit_width = 24;
+
+    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)
+                session_output_config.output_config->bit_width = 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_BROADCAST, ms12_lib_handle);
+        if (qap_session_handle == NULL)
+            return -EINVAL;
+    } else if ((session_type == SESSION_BROADCAST) && dts_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 && dts_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 && dts_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);
+    if (ret != QAP_STATUS_OK) {
+        fprintf(stderr, "!!!! Please specify appropriate Session\n");
+        return -EINVAL;
+    }
+
+    if (stream->filetype == FILE_DTS) {
+        ALOGV("Session set params %s", session_kv_pairs);
+        ret = qap_session_cmd(qap_session_handle, QAP_SESSION_CMD_SET_KVPAIRS, sizeof(session_kv_pairs), session_kv_pairs, NULL, NULL);
+        if (ret != QAP_STATUS_OK) {
+            fprintf(stderr, "Session set params failed\n");
+            return -EINVAL;
+        }
+    }
+
+    pthread_mutex_init(&main_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(&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");
+    qap_session_close(qap_session_handle);
+    qap_session_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);
+        pthread_exit(0);
+    }
+    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__);
+        pthread_exit(0);
+    }
+    buffer->common_params.data = calloc(1, FRAME_SIZE);
+    if (buffer->common_params.data == NULL) {
+        fprintf(stderr, "%s::%d: Memory Alloc Error\n", __func__, __LINE__);
+        pthread_exit(0);
+        if (NULL != buffer) {
+            free( buffer);
+            buffer = 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");
+        pthread_exit(0);
+        if (NULL != buffer &&  NULL != buffer->common_params.data) {
+            free( buffer->common_params.data);
+            buffer->common_params.data = NULL;
+            free( buffer);
+            buffer = 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);
+            }
+        }
+        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 (kpi_mode) {
+            if (stream_info->framesize_filename != NULL) {
+                if (!stream_info->framesize_file_ptr) {
+                    stream_info->framesize_file_ptr = fopen(stream_info->framesize_filename, "r");
+                    if (!stream_info->framesize_file_ptr) {
+                        fprintf(stderr, "Cannot open audio file %s\n", stream_info->framesize_filename);
+                        goto exit;
+                    }
+                }
+                qap_wrapper_read_frame_size_from_file(buffer, stream_info->framesize_file_ptr);
+            } else {
+                fprintf(stdout, "%s Could not found frame size file\n", __FUNCTION__);
+                goto exit;
+            }
+        }
+
+        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(data_buf, 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) {
+            buffer->buffer_parms.input_buf_params.flags = QAP_BUFFER_EOS;
+            bytes_consumed = qap_module_process(qap_module_handle, buffer);
+            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;
+        if (kpi_mode)
+            data_write_count++;
+        do {
+            if (kpi_mode) {
+                if (data_write_count == 16) {
+                    tcont_start = clock();
+                } else if (data_write_count == 18) {
+                    buffer->buffer_parms.input_buf_params.flags = QAP_BUFFER_EOS;
+                    bytes_consumed = qap_module_process(qap_module_handle, buffer);
+                    qap_module_cmd(qap_module_handle, QAP_MODULE_CMD_STOP, sizeof(QAP_MODULE_CMD_STOP), NULL, NULL, NULL);
+                    goto wait_for_eos;
+                }
+            }
+            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 feeding Input of size %d  and bytes_cosumed is %d",
+                      __FUNCTION__, __LINE__,bytes_read, bytes_consumed);
+            if ((format == QAP_AUDIO_FORMAT_DTS) ||
+                 (format == QAP_AUDIO_FORMAT_DTS_HD)) {
+                  if (bytes_consumed < 0) {
+                      while (!is_buffer_available) {
+                          usleep(1000);
+                          ret = qap_module_cmd(qap_module_handle, QAP_MODULE_CMD_GET_PARAM,
+                                 sizeof(QAP_MODULE_CMD_GET_PARAM), "buf_available", NULL, reply_data
+                          );
+                          if (reply_data)
+                              temp_str = get_string_value(reply_data, &status);
+                           if (temp_str) {
+                               is_buffer_available = atoi(temp_str);
+                               free(temp_str);
+                           }
+                           ALOGV("%s : %d, dts clip reply_data is %d buffer availabale is %d",
+                                 __FUNCTION__, __LINE__, reply_data, is_buffer_available);
+                       }
+                  }
+             }
+        } while (buffer->common_params.size > 0);
+        if (reply_data)
+            free(reply_data);
+        buffer->common_params.data = temp_ptr;
+        if (!(stream_info->system_input || stream_info->sec_input)) {
+            usleep(5000); //To swtich between main and secondary threads incase of dual input
+        }
+    } while (1);
+
+wait_for_eos:
+    if (stream_info->sec_input && !stream_info->aac_fmt_type) {
+        pthread_mutex_lock(&sec_eos_lock);
+        pthread_cond_wait(&sec_eos_cond, &sec_eos_lock);
+        pthread_mutex_unlock(&sec_eos_lock);
+        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)){
+        pthread_mutex_lock(&main_eos_lock);
+        pthread_cond_wait(&main_eos_cond, &main_eos_lock);
+        pthread_mutex_unlock(&main_eos_lock);
+        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);
+    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 = NULL;
+    int ret = 0;
+    int i = 0;
+    stream_config *stream_info = (stream_config *)stream_data;
+    qap_module_handle_t qap_module_handle = NULL;
+
+    input_config = (qap_module_config_t *) calloc(1, sizeof(qap_module_config_t));
+    if (input_config == NULL) {
+        fprintf(stderr, "%s::%d Memory Alloc Error\n", __func__, __LINE__);
+        return 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;
+
+    stream_info->bytes_to_read = 1024;
+    input_streams_count++;
+    if (input_streams_count == 2) {
+        if (stream_info->filetype == FILE_WAV) {
+            input_config->flags = QAP_MODULE_FLAG_SYSTEM_SOUND;
+            stream_info->system_input = true;
+            has_system_input = true;
+            ALOGV("%s::%d Set Secondary System Sound Flag", __func__, __LINE__);
+        } else if (stream_info->filetype != FILE_WAV) {
+            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->filetype == FILE_WAV) {
+            ALOGV("%s::%d Set Secondary System Sound Flag", __func__, __LINE__);
+            input_config->flags = QAP_MODULE_FLAG_SYSTEM_SOUND;
+            stream_info->system_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;
+
+    if (!session_output_configured) {
+        session_output_config.output_config->channels = input_config->channels;
+        session_output_config.output_config->sample_rate = input_config->sample_rate;
+        output_device_id = stream_info->output_device;
+        if (output_device_id == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) {
+            output_device_id = AUDIO_DEVICE_OUT_SPEAKER;
+            play_through_bt = true;
+        }
+        if (output_device_id == AUDIO_DEVICE_OUT_LINE) {
+            output_device_id = AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
+        }
+        session_output_config.output_config->id = output_device_id;
+        if (stream_info->filetype != FILE_DTS)
+            session_output_config.output_config->bit_width = input_config->bit_width;
+        session_output_config.output_config->is_interleaved = input_config->is_interleaved;
+        session_output_config.num_output = 1;
+
+        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 NULL;
+        }
+
+        if (stream_info->filetype != FILE_DTS) {
+            ALOGV("Session set params %s", session_kv_pairs);
+            ret = qap_session_cmd(qap_session_handle, QAP_SESSION_CMD_SET_KVPAIRS, sizeof(session_kv_pairs), session_kv_pairs, NULL, NULL);
+            if (ret != QAP_STATUS_OK) {
+                fprintf(stderr, "Session set params failed\n");
+                return NULL;
+            }
+        }
+        session_output_configured = true;
+    }
+
+    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;
+    }
+
+    return qap_module_handle;
+
+}
+
+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");
+}