agm: add compress capture support

add new agm session mode for compress sessions
and changes to support TX path in tinycompress plugin.
Also, add changes to configure encoder module.

Change-Id: Iaa5e05611be276f20cd0a0ba784917a889244e82
diff --git a/plugins/tinyalsa/src/agm_compress_plugin.c b/plugins/tinyalsa/src/agm_compress_plugin.c
index fef9143..d8f5cdf 100644
--- a/plugins/tinyalsa/src/agm_compress_plugin.c
+++ b/plugins/tinyalsa/src/agm_compress_plugin.c
@@ -25,6 +25,39 @@
 ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 ** OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 ** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+** Changes from Qualcomm Innovation Center are provided under the following license:
+** Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted (subject to the limitations in the
+** disclaimer below) provided that the following conditions are met:
+**
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**
+**   * Redistributions in binary form must reproduce the above
+**     copyright notice, this list of conditions and the following
+**     disclaimer in the documentation and/or other materials provided
+**     with the distribution.
+**
+**   * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+** NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+** GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+** HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+** IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+** GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+** IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 **/
 #define LOG_TAG "PLUGIN: compress"
 
@@ -215,8 +248,10 @@
         will be called before start() */
     if (!priv->prepared) {
         ret = agm_session_prepare(handle);
-        if (ret)
+        if (ret) {
+            errno = ret;
             return ret;
+        }
         priv->prepared = true;
     }
 
@@ -253,6 +288,7 @@
     struct agm_compress_priv *priv = plugin->priv;
     uint64_t handle;
     int ret = 0, buf_cnt = 0;
+    AGM_LOGV("Enter");
 
     ret = agm_get_session_handle(priv, &handle);
     if (ret)
@@ -270,20 +306,11 @@
     }
     pthread_mutex_lock(&priv->lock);
 
-    buf_cnt = count / priv->buffer_config.size;
-    if (count % priv->buffer_config.size != 0)
-        buf_cnt +=1;
-
-    /* Avalible buffer size is always multiple of fragment size */
-    priv->bytes_avail -= (buf_cnt * priv->buffer_config.size);
-    if (priv->bytes_avail < 0)
-        AGM_LOGE("%s: err: bytes_avail = %lld", __func__, (long long) priv->bytes_avail);
-
     priv->bytes_read += count;
 
     pthread_mutex_unlock(&priv->lock);
-
-    return 0;
+    AGM_LOGV("Exit: read bytes: %d",count);
+    return count;
 }
 
 int agm_compress_tstamp(struct compress_plugin *plugin,
@@ -373,70 +400,95 @@
     media_cfg->rate =  params->codec.sample_rate;
     media_cfg->channels = params->codec.ch_out;
 
-    switch (params->codec.id) {
-    case SND_AUDIOCODEC_MP3:
-        media_cfg->format = AGM_FORMAT_MP3;
-        break;
-    case SND_AUDIOCODEC_AAC:
-        media_cfg->format = AGM_FORMAT_AAC;
-        if (params->codec.format == SND_AUDIOSTREAMFORMAT_MP4LATM)
-            sess_cfg->codec.aac_dec.aac_fmt_flag = 0x04;
-        else if (params->codec.format == SND_AUDIOSTREAMFORMAT_ADIF)
-            sess_cfg->codec.aac_dec.aac_fmt_flag = 0x02;
-        else if (params->codec.format == SND_AUDIOSTREAMFORMAT_MP4ADTS)
-            sess_cfg->codec.aac_dec.aac_fmt_flag = 0x00;
-        else
-            sess_cfg->codec.aac_dec.aac_fmt_flag = 0x03;
-        sess_cfg->codec.aac_dec.num_channels = params->codec.ch_in;
-        sess_cfg->codec.aac_dec.sample_rate = media_cfg->rate;
-        break;
-    case SND_AUDIOCODEC_FLAC:
-        media_cfg->format = AGM_FORMAT_FLAC;
-        sess_cfg->codec.flac_dec.num_channels = params->codec.ch_in;
-        sess_cfg->codec.flac_dec.sample_rate = media_cfg->rate;
-        break;
-#ifdef SND_AUDIOCODEC_ALAC
-    case SND_AUDIOCODEC_ALAC:
-        media_cfg->format = AGM_FORMAT_ALAC;
-        sess_cfg->codec.alac_dec.num_channels = params->codec.ch_in;
-        sess_cfg->codec.alac_dec.sample_rate = media_cfg->rate;
-        break;
-#endif
-#ifdef SND_AUDIOCODEC_APE
-    case SND_AUDIOCODEC_APE:
-        media_cfg->format = AGM_FORMAT_APE;
-        sess_cfg->codec.ape_dec.num_channels = params->codec.ch_in;
-        sess_cfg->codec.ape_dec.sample_rate = media_cfg->rate;
-        break;
-#endif
-    case SND_AUDIOCODEC_WMA:
-#ifdef SND_AUDIOPROFILE_WMA9_LOSSLESS
-        if ((params->codec.profile == SND_AUDIOPROFILE_WMA9_PRO) ||
-            (params->codec.profile == SND_AUDIOPROFILE_WMA9_LOSSLESS) ||
-            (params->codec.profile == SND_AUDIOPROFILE_WMA10_LOSSLESS)) {
-#else
-        if ((params->codec.profile == SND_AUDIOMODE_WMAPRO_LEVELM0) ||
-            (params->codec.profile == SND_AUDIOMODE_WMAPRO_LEVELM1) ||
-            (params->codec.profile == SND_AUDIOMODE_WMAPRO_LEVELM2)) {
-#endif
-            media_cfg->format = AGM_FORMAT_WMAPRO;
-            sess_cfg->codec.wmapro_dec.fmt_tag = params->codec.format;
-            sess_cfg->codec.wmapro_dec.num_channels = params->codec.ch_in;
-            sess_cfg->codec.wmapro_dec.sample_rate = media_cfg->rate;
-        } else {
-            media_cfg->format = AGM_FORMAT_WMASTD;
-            sess_cfg->codec.wma_dec.fmt_tag = params->codec.format;
-            sess_cfg->codec.wma_dec.num_channels = params->codec.ch_in;
-            sess_cfg->codec.wma_dec.sample_rate = media_cfg->rate;
+    if (sess_cfg->dir == RX) {
+        switch (params->codec.id) {
+        case SND_AUDIOCODEC_MP3:
+            media_cfg->format = AGM_FORMAT_MP3;
+            break;
+        case SND_AUDIOCODEC_AAC:
+            media_cfg->format = AGM_FORMAT_AAC;
+            if (params->codec.format == SND_AUDIOSTREAMFORMAT_MP4LATM)
+                sess_cfg->codec.aac_dec.aac_fmt_flag = 0x04;
+            else if (params->codec.format == SND_AUDIOSTREAMFORMAT_ADIF)
+                sess_cfg->codec.aac_dec.aac_fmt_flag = 0x02;
+            else if (params->codec.format == SND_AUDIOSTREAMFORMAT_MP4ADTS)
+                sess_cfg->codec.aac_dec.aac_fmt_flag = 0x00;
+            else
+                sess_cfg->codec.aac_dec.aac_fmt_flag = 0x03;
+            sess_cfg->codec.aac_dec.num_channels = params->codec.ch_in;
+            sess_cfg->codec.aac_dec.sample_rate = media_cfg->rate;
+            break;
+        case SND_AUDIOCODEC_FLAC:
+            media_cfg->format = AGM_FORMAT_FLAC;
+            sess_cfg->codec.flac_dec.num_channels = params->codec.ch_in;
+            sess_cfg->codec.flac_dec.sample_rate = media_cfg->rate;
+            break;
+    #ifdef SND_AUDIOCODEC_ALAC
+        case SND_AUDIOCODEC_ALAC:
+            media_cfg->format = AGM_FORMAT_ALAC;
+            sess_cfg->codec.alac_dec.num_channels = params->codec.ch_in;
+            sess_cfg->codec.alac_dec.sample_rate = media_cfg->rate;
+            break;
+    #endif
+    #ifdef SND_AUDIOCODEC_APE
+        case SND_AUDIOCODEC_APE:
+            media_cfg->format = AGM_FORMAT_APE;
+            sess_cfg->codec.ape_dec.num_channels = params->codec.ch_in;
+            sess_cfg->codec.ape_dec.sample_rate = media_cfg->rate;
+            break;
+    #endif
+        case SND_AUDIOCODEC_WMA:
+    #ifdef SND_AUDIOPROFILE_WMA9_LOSSLESS
+            if ((params->codec.profile == SND_AUDIOPROFILE_WMA9_PRO) ||
+                (params->codec.profile == SND_AUDIOPROFILE_WMA9_LOSSLESS) ||
+                (params->codec.profile == SND_AUDIOPROFILE_WMA10_LOSSLESS)) {
+    #else
+            if ((params->codec.profile == SND_AUDIOMODE_WMAPRO_LEVELM0) ||
+                (params->codec.profile == SND_AUDIOMODE_WMAPRO_LEVELM1) ||
+                (params->codec.profile == SND_AUDIOMODE_WMAPRO_LEVELM2)) {
+    #endif
+                media_cfg->format = AGM_FORMAT_WMAPRO;
+                sess_cfg->codec.wmapro_dec.fmt_tag = params->codec.format;
+                sess_cfg->codec.wmapro_dec.num_channels = params->codec.ch_in;
+                sess_cfg->codec.wmapro_dec.sample_rate = media_cfg->rate;
+            } else {
+                media_cfg->format = AGM_FORMAT_WMASTD;
+                sess_cfg->codec.wma_dec.fmt_tag = params->codec.format;
+                sess_cfg->codec.wma_dec.num_channels = params->codec.ch_in;
+                sess_cfg->codec.wma_dec.sample_rate = media_cfg->rate;
+            }
+            break;
+        case SND_AUDIOCODEC_VORBIS:
+            media_cfg->format = AGM_FORMAT_VORBIS;
+            break;
+        default:
+            break;
         }
-        break;
-    case SND_AUDIOCODEC_VORBIS:
-        media_cfg->format = AGM_FORMAT_VORBIS;
-        break;
-    default:
-        break;
     }
 
+    // capture path
+    if (sess_cfg->dir == TX) {
+        switch (params->codec.id) {
+        case SND_AUDIOCODEC_AAC:
+            media_cfg->format = AGM_FORMAT_AAC;
+
+            sess_cfg->codec.aac_enc.aac_bit_rate = params->codec.bit_rate;
+            sess_cfg->codec.aac_enc.enc_cfg.aac_enc_mode =
+                params->codec.profile;
+            sess_cfg->codec.aac_enc.enc_cfg.aac_fmt_flag = params->codec.format;
+
+            AGM_LOGD(
+                "%s: requested configuration, AAC encode mode: %x, AAC format "
+                "flag: %x, AAC bit rate: %d",
+                __func__, sess_cfg->codec.aac_enc.enc_cfg.aac_enc_mode,
+                sess_cfg->codec.aac_enc.enc_cfg.aac_fmt_flag,
+                sess_cfg->codec.aac_enc.aac_bit_rate);
+            break;
+
+        default:
+            break;
+        }
+    }
     agm_session_update_codec_options(sess_cfg, params);
 
     AGM_LOGD("%s: format = %d rate = %d, channels = %d\n", __func__,
@@ -465,14 +517,20 @@
     priv->total_buf_size = buf_cfg->size * buf_cfg->count;
 
     sess_cfg = &priv->session_config;
+
     if (sess_cfg->dir == RX)
         priv->bytes_avail = priv->total_buf_size;
     else
-        priv->bytes_avail = 0;
+        priv->bytes_avail = priv->total_buf_size;
 
     sess_cfg->start_threshold = 0;
     sess_cfg->stop_threshold = 0;
-    sess_cfg->data_mode = AGM_DATA_NON_BLOCKING;
+
+    if (sess_cfg->dir == RX)
+        sess_cfg->data_mode = AGM_DATA_NON_BLOCKING;
+    else
+        sess_cfg->data_mode = AGM_DATA_BLOCKING;
+
     /* Populate each codec format specific params */
     ret = agm_session_update_codec_config(priv, params);
     if (ret)
@@ -526,6 +584,20 @@
     if (ret)
         return ret;
 
+    /**
+     * Unlike playback, for capture case, call
+     * agm_session_prepare it in start.
+     * For playback it is called in write.
+     * */
+    if (!priv->prepared) {
+        ret = agm_session_prepare(handle);
+        if (ret) {
+            errno = ret;
+            return ret;
+        }
+        priv->prepared = true;
+    }
+
     ret = agm_session_start(handle);
     if (ret)
         errno = ret;
@@ -746,10 +818,13 @@
     if (ret)
         return;
 
-    ret = agm_session_register_cb(priv->session_id, NULL,
-                                  AGM_EVENT_DATA_PATH, plugin);
-    ret = agm_session_register_cb(priv->session_id, NULL,
-                                  AGM_EVENT_MODULE, plugin);
+    if (priv->session_config.dir == RX) {
+        ret = agm_session_register_cb(priv->session_id, NULL,
+                                    AGM_EVENT_DATA_PATH, plugin);
+        ret = agm_session_register_cb(priv->session_id, NULL,
+                                    AGM_EVENT_MODULE, plugin);
+    }
+
     ret = agm_session_close(handle);
     if (ret)
         AGM_LOGE("%s: agm_session_close failed \n", __func__);
@@ -805,7 +880,12 @@
 static int agm_populate_codec_caps(struct agm_compress_priv *priv)
 {
     int codec_count = 0;
-    priv->compr_cap.direction = SND_COMPRESS_PLAYBACK;
+
+    if (priv->session_config.dir == RX)
+        priv->compr_cap.direction = SND_COMPRESS_PLAYBACK;
+    else
+        priv->compr_cap.direction = SND_COMPRESS_CAPTURE;
+
     priv->compr_cap.min_fragment_size =
                     COMPR_PLAYBACK_MIN_FRAGMENT_SIZE;
     priv->compr_cap.max_fragment_size =
@@ -887,6 +967,8 @@
     priv->session_config.sess_mode = sess_mode;
     priv->session_config.dir = (flags & COMPRESS_IN) ? RX : TX;
     priv->session_id = session_id;
+    AGM_LOGD("%s: requested agm session mode: %zu", __func__,
+             priv->session_config.sess_mode);
 
     if ((priv->session_config.dir == RX) && !is_playback) {
         AGM_LOGE("%s: Playback is supported for device %d \n",
@@ -904,13 +986,26 @@
         errno = ret;
         goto err_card_put;
     }
-    ret = agm_session_register_cb(session_id, &agm_compress_event_cb,
-                                  AGM_EVENT_DATA_PATH, agm_compress_plugin);
-    if (ret)
-        goto err_sess_cls;
 
-    ret = agm_session_register_cb(session_id, &agm_compress_event_cb,
+    // TODO introduce nonblock flag here
+    // instead of checking with direction and then registering callback
+    // use nonblock flag and then register call back
+    /**
+     * the agm call back aren't required for capture usecase. since
+     * the read calls to agm are data blocking.
+     * */
+    if (priv->session_config.dir == RX) {
+        ret = agm_session_register_cb(session_id, &agm_compress_event_cb,
+                                  AGM_EVENT_DATA_PATH, agm_compress_plugin);
+        if (ret)
+            goto err_sess_cls;
+
+        ret = agm_session_register_cb(session_id, &agm_compress_event_cb,
                                   AGM_EVENT_MODULE, agm_compress_plugin);
+        if (ret)
+            goto err_sess_cls;
+    }
+
     agm_populate_codec_caps(priv);
     priv->handle = handle;
     *plugin = agm_compress_plugin;
@@ -942,70 +1037,84 @@
 
     union snd_codec_options *copt = &params->codec.options;
 
-    switch (params->codec.id) {
-    case SND_AUDIOCODEC_AAC:
-        sess_cfg->codec.aac_dec.audio_obj_type = copt->generic.reserved[0];
-        sess_cfg->codec.aac_dec.total_size_of_PCE_bits = copt->generic.reserved[1];
-        break;
-    case SND_AUDIOCODEC_FLAC:
-        sess_cfg->codec.flac_dec.sample_size = copt->generic.reserved[0];
-        sess_cfg->codec.flac_dec.min_blk_size = copt->generic.reserved[1];
-        sess_cfg->codec.flac_dec.max_blk_size = copt->generic.reserved[2];
-        sess_cfg->codec.flac_dec.min_frame_size = copt->generic.reserved[3];
-        sess_cfg->codec.flac_dec.max_frame_size = copt->generic.reserved[4];
-        break;
-#ifdef SND_AUDIOCODEC_ALAC
-    case SND_AUDIOCODEC_ALAC:
-        sess_cfg->codec.alac_dec.frame_length = copt->generic.reserved[0];
-        sess_cfg->codec.alac_dec.compatible_version = copt->generic.reserved[1];
-        sess_cfg->codec.alac_dec.bit_depth = copt->generic.reserved[2];
-        sess_cfg->codec.alac_dec.pb = copt->generic.reserved[3];
-        sess_cfg->codec.alac_dec.mb = copt->generic.reserved[4];
-        sess_cfg->codec.alac_dec.kb = copt->generic.reserved[5];
-        sess_cfg->codec.alac_dec.max_run = copt->generic.reserved[6];
-        sess_cfg->codec.alac_dec.max_frame_bytes = copt->generic.reserved[7];
-        sess_cfg->codec.alac_dec.avg_bit_rate = copt->generic.reserved[8];
-        sess_cfg->codec.alac_dec.channel_layout_tag = copt->generic.reserved[9];
-        break;
-#endif
-#ifdef SND_AUDIOCODEC_APE
-    case SND_AUDIOCODEC_APE:
-        sess_cfg->codec.ape_dec.bit_width = copt->generic.reserved[0];
-        sess_cfg->codec.ape_dec.compatible_version = copt->generic.reserved[1];
-        sess_cfg->codec.ape_dec.compression_level = copt->generic.reserved[2];
-        sess_cfg->codec.ape_dec.format_flags = copt->generic.reserved[3];
-        sess_cfg->codec.ape_dec.blocks_per_frame = copt->generic.reserved[4];
-        sess_cfg->codec.ape_dec.final_frame_blocks = copt->generic.reserved[5];
-        sess_cfg->codec.ape_dec.total_frames = copt->generic.reserved[6];
-        sess_cfg->codec.ape_dec.seek_table_present = copt->generic.reserved[7];
-        break;
-#endif
-    case SND_AUDIOCODEC_WMA:
-#ifdef SND_AUDIOPROFILE_WMA9_LOSSLESS
-        if ((params->codec.profile == SND_AUDIOPROFILE_WMA9_PRO) ||
-            (params->codec.profile == SND_AUDIOPROFILE_WMA9_LOSSLESS) ||
-            (params->codec.profile == SND_AUDIOPROFILE_WMA10_LOSSLESS)) {
-#else
-        if ((params->codec.profile == SND_AUDIOMODE_WMAPRO_LEVELM0) ||
-            (params->codec.profile == SND_AUDIOMODE_WMAPRO_LEVELM1) ||
-            (params->codec.profile == SND_AUDIOMODE_WMAPRO_LEVELM2)) {
-#endif
-            sess_cfg->codec.wmapro_dec.avg_bytes_per_sec = copt->generic.reserved[0];
-            sess_cfg->codec.wmapro_dec.blk_align = copt->generic.reserved[1];
-            sess_cfg->codec.wmapro_dec.bits_per_sample = copt->generic.reserved[2];
-            sess_cfg->codec.wmapro_dec.channel_mask = copt->generic.reserved[3];
-            sess_cfg->codec.wmapro_dec.enc_options = copt->generic.reserved[4];
-            sess_cfg->codec.wmapro_dec.advanced_enc_option = copt->generic.reserved[5];
-            sess_cfg->codec.wmapro_dec.advanced_enc_option2 = copt->generic.reserved[6];
-        } else {
-            sess_cfg->codec.wma_dec.avg_bytes_per_sec = copt->generic.reserved[0];
-            sess_cfg->codec.wma_dec.blk_align = copt->generic.reserved[1];
-            sess_cfg->codec.wma_dec.bits_per_sample = copt->generic.reserved[2];
-            sess_cfg->codec.wma_dec.channel_mask = copt->generic.reserved[3];
-            sess_cfg->codec.wma_dec.enc_options = copt->generic.reserved[4];
+    // playback
+    if (sess_cfg->dir == RX) {
+        switch (params->codec.id) {
+        case SND_AUDIOCODEC_AAC:
+            sess_cfg->codec.aac_dec.audio_obj_type = copt->generic.reserved[0];
+            sess_cfg->codec.aac_dec.total_size_of_PCE_bits = copt->generic.reserved[1];
+            break;
+        case SND_AUDIOCODEC_FLAC:
+            sess_cfg->codec.flac_dec.sample_size = copt->generic.reserved[0];
+            sess_cfg->codec.flac_dec.min_blk_size = copt->generic.reserved[1];
+            sess_cfg->codec.flac_dec.max_blk_size = copt->generic.reserved[2];
+            sess_cfg->codec.flac_dec.min_frame_size = copt->generic.reserved[3];
+            sess_cfg->codec.flac_dec.max_frame_size = copt->generic.reserved[4];
+            break;
+    #ifdef SND_AUDIOCODEC_ALAC
+        case SND_AUDIOCODEC_ALAC:
+            sess_cfg->codec.alac_dec.frame_length = copt->generic.reserved[0];
+            sess_cfg->codec.alac_dec.compatible_version = copt->generic.reserved[1];
+            sess_cfg->codec.alac_dec.bit_depth = copt->generic.reserved[2];
+            sess_cfg->codec.alac_dec.pb = copt->generic.reserved[3];
+            sess_cfg->codec.alac_dec.mb = copt->generic.reserved[4];
+            sess_cfg->codec.alac_dec.kb = copt->generic.reserved[5];
+            sess_cfg->codec.alac_dec.max_run = copt->generic.reserved[6];
+            sess_cfg->codec.alac_dec.max_frame_bytes = copt->generic.reserved[7];
+            sess_cfg->codec.alac_dec.avg_bit_rate = copt->generic.reserved[8];
+            sess_cfg->codec.alac_dec.channel_layout_tag = copt->generic.reserved[9];
+            break;
+    #endif
+    #ifdef SND_AUDIOCODEC_APE
+        case SND_AUDIOCODEC_APE:
+            sess_cfg->codec.ape_dec.bit_width = copt->generic.reserved[0];
+            sess_cfg->codec.ape_dec.compatible_version = copt->generic.reserved[1];
+            sess_cfg->codec.ape_dec.compression_level = copt->generic.reserved[2];
+            sess_cfg->codec.ape_dec.format_flags = copt->generic.reserved[3];
+            sess_cfg->codec.ape_dec.blocks_per_frame = copt->generic.reserved[4];
+            sess_cfg->codec.ape_dec.final_frame_blocks = copt->generic.reserved[5];
+            sess_cfg->codec.ape_dec.total_frames = copt->generic.reserved[6];
+            sess_cfg->codec.ape_dec.seek_table_present = copt->generic.reserved[7];
+            break;
+    #endif
+        case SND_AUDIOCODEC_WMA:
+    #ifdef SND_AUDIOPROFILE_WMA9_LOSSLESS
+            if ((params->codec.profile == SND_AUDIOPROFILE_WMA9_PRO) ||
+                (params->codec.profile == SND_AUDIOPROFILE_WMA9_LOSSLESS) ||
+                (params->codec.profile == SND_AUDIOPROFILE_WMA10_LOSSLESS)) {
+    #else
+            if ((params->codec.profile == SND_AUDIOMODE_WMAPRO_LEVELM0) ||
+                (params->codec.profile == SND_AUDIOMODE_WMAPRO_LEVELM1) ||
+                (params->codec.profile == SND_AUDIOMODE_WMAPRO_LEVELM2)) {
+    #endif
+                sess_cfg->codec.wmapro_dec.avg_bytes_per_sec = copt->generic.reserved[0];
+                sess_cfg->codec.wmapro_dec.blk_align = copt->generic.reserved[1];
+                sess_cfg->codec.wmapro_dec.bits_per_sample = copt->generic.reserved[2];
+                sess_cfg->codec.wmapro_dec.channel_mask = copt->generic.reserved[3];
+                sess_cfg->codec.wmapro_dec.enc_options = copt->generic.reserved[4];
+                sess_cfg->codec.wmapro_dec.advanced_enc_option = copt->generic.reserved[5];
+                sess_cfg->codec.wmapro_dec.advanced_enc_option2 = copt->generic.reserved[6];
+            } else {
+                sess_cfg->codec.wma_dec.avg_bytes_per_sec = copt->generic.reserved[0];
+                sess_cfg->codec.wma_dec.blk_align = copt->generic.reserved[1];
+                sess_cfg->codec.wma_dec.bits_per_sample = copt->generic.reserved[2];
+                sess_cfg->codec.wma_dec.channel_mask = copt->generic.reserved[3];
+                sess_cfg->codec.wma_dec.enc_options = copt->generic.reserved[4];
+            }
+            break;
+        default:
+            break;
         }
-        break;
-    default:
-        break;
+    }
+
+    // capture
+    if (sess_cfg->dir == TX) {
+        switch (params->codec.id) {
+        case SND_AUDIOCODEC_AAC:
+            break;
+
+        default:
+            break;
+        }
     }
 }
diff --git a/service/inc/public/agm/agm_api.h b/service/inc/public/agm/agm_api.h
index f366088..420afa7 100644
--- a/service/inc/public/agm/agm_api.h
+++ b/service/inc/public/agm/agm_api.h
@@ -58,6 +58,40 @@
  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+**
+** Changes from Qualcomm Innovation Center are provided under the following license:
+** Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted (subject to the limitations in the
+** disclaimer below) provided that the following conditions are met:
+**
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**
+**   * Redistributions in binary form must reproduce the above
+**     copyright notice, this list of conditions and the following
+**     disclaimer in the documentation and/or other materials provided
+**     with the distribution.
+**
+**   * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+** NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+** GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+** HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+** IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+** GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+** IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifndef _AGM_INTF_H_
@@ -180,6 +214,7 @@
     AGM_SESSION_NO_HOST,         /**< Hostless mode */
     AGM_SESSION_NON_TUNNEL,      /**< Non tunnel mode */
     AGM_SESSION_NO_CONFIG,       /**< No Config mode*/
+    AGM_SESSION_COMPRESS,        /**< Compress mode*/
 };
 
 struct agm_extern_alloc_buff_info{
@@ -219,6 +254,19 @@
 };
 
 /**
+ * AAC encoder parameters
+ */
+struct agm_session_aac_enc_cfg {
+    uint16_t aac_enc_mode; /**< AAC encoder mode */
+    uint16_t aac_fmt_flag; /**< AAC format flag */
+};
+
+struct agm_session_aac_enc {
+    uint32_t aac_bit_rate;
+    struct agm_session_aac_enc_cfg enc_cfg;
+};
+
+/**
  * FLAC decoder parameters
  */
 struct agm_session_flac_dec {
@@ -302,6 +350,7 @@
 union agm_session_codec
 {
     struct agm_session_aac_dec aac_dec;        /**< AAC decoder config */
+    struct agm_session_aac_enc aac_enc;        /**< AAC encoder config */
     struct agm_session_flac_dec flac_dec;      /**< Flac decoder config */
     struct agm_session_alac_dec alac_dec;      /**< Alac decoder config */
     struct agm_session_ape_dec ape_dec;        /**< APE decoder config */
diff --git a/service/src/graph.c b/service/src/graph.c
index 50f8d33..577f5ef 100644
--- a/service/src/graph.c
+++ b/service/src/graph.c
@@ -26,6 +26,39 @@
  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+** Changes from Qualcomm Innovation Center are provided under the following license:
+** Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted (subject to the limitations in the
+** disclaimer below) provided that the following conditions are met:
+**
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**
+**   * Redistributions in binary form must reproduce the above
+**     copyright notice, this list of conditions and the following
+**     disclaimer in the documentation and/or other materials provided
+**     with the distribution.
+**
+**   * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+** NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+** GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+** HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+** IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+** GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+** IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #define LOG_TAG "AGM: graph"
 
@@ -236,6 +269,9 @@
 
         if (mode == AGM_DATA_PUSH_PULL)
             buf_config.shmem_ep_tag = PULL_PUSH_SHMEM_ENDPOINT;
+        else if ((sess_obj->stream_config.sess_mode == AGM_SESSION_COMPRESS) &&
+                 (sess_obj->stream_config.dir == TX))
+            buf_config.shmem_ep_tag = RD_SHMEM_ENDPOINT;
         else
             buf_config.shmem_ep_tag = SHMEM_ENDPOINT;
         /**
@@ -1316,6 +1352,10 @@
     if ((graph_obj->sess_obj->stream_config.sess_mode == AGM_SESSION_NON_TUNNEL) &&
         (graph_obj->sess_obj->stream_config.dir == (RX | TX)))
          read_mod_tag = RD_SHMEM_ENDPOINT;
+    else if ((graph_obj->sess_obj->stream_config.sess_mode ==
+              AGM_SESSION_COMPRESS) &&
+             (graph_obj->sess_obj->stream_config.dir == TX))
+         read_mod_tag = RD_SHMEM_ENDPOINT;
 
     gsl_buff.timestamp = buffer->timestamp;
     gsl_buff.flags = buffer->flags;
diff --git a/service/src/graph_module.c b/service/src/graph_module.c
index 83e5c10..f77aa0f 100644
--- a/service/src/graph_module.c
+++ b/service/src/graph_module.c
@@ -59,6 +59,39 @@
  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+** Changes from Qualcomm Innovation Center are provided under the following license:
+** Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted (subject to the limitations in the
+** disclaimer below) provided that the following conditions are met:
+**
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**
+**   * Redistributions in binary form must reproduce the above
+**     copyright notice, this list of conditions and the following
+**     disclaimer in the documentation and/or other materials provided
+**     with the distribution.
+**
+**   * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+** NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+** GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+** HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+** IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+** GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+** IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #define LOG_TAG "AGM: graph_module"
@@ -215,8 +248,9 @@
     case AGM_FORMAT_MP3:
     case AGM_FORMAT_AAC:
     default:
-         break;
+        break;
     }
+    AGM_LOGD("%s: bit width: %d", __func__, bit_width);
 
     return bit_width;
 }
@@ -1264,6 +1298,149 @@
 }
 
 /**
+ *  codec specific encoder config only for TX type
+ */
+int configure_encoder_output_media_format(struct module_info *mod,
+                                          struct graph_obj *graph_obj) {
+    int ret = 0;
+    struct session_obj *sess_obj = graph_obj->sess_obj;
+    struct apm_module_param_data_t *header;
+    struct param_id_encoder_output_config_t *enc_out_conf_param;
+    uint8_t *payload = NULL;
+    size_t payload_size = 0;
+    size_t size_apm_module = sizeof(struct apm_module_param_data_t);
+    size_t size_encoder_config =
+        sizeof(struct param_id_encoder_output_config_t);
+    size_t size_apm_and_encoder_config = size_apm_module + size_encoder_config;
+    AGM_LOGV("Enter");
+
+    /**
+     * For Encoder module, PARAM_ID_ENCODER_OUTPUT_CONFIG
+     * */
+
+    /**
+     * only TX session, hence in media config
+     * */
+    switch (sess_obj->in_media_config.format) {
+        case AGM_FORMAT_AAC: {
+            size_t size_aac_cfg = sizeof(struct aac_enc_cfg_t);
+            payload_size = size_apm_and_encoder_config + size_aac_cfg;
+
+            /*ensure that the payloadszie is byte multiple atleast*/
+            ALIGN_PAYLOAD(payload_size, 8);
+            payload = (uint8_t *)calloc(1, payload_size);
+            if (!payload) {
+                AGM_LOGE("Not enough memory for payload");
+                ret = -ENOMEM;
+                goto err;
+            }
+
+            struct param_id_encoder_output_config_t enc_out_conf_param;
+            enc_out_conf_param.data_format = AGM_DATA_FORMAT_FIXED_POINT;
+            enc_out_conf_param.fmt_id = MEDIA_FMT_AAC;
+            enc_out_conf_param.payload_size = size_aac_cfg;
+            memcpy(payload + size_apm_module, &enc_out_conf_param,
+                   size_encoder_config);
+
+            memcpy(payload + size_apm_and_encoder_config,
+                   &(sess_obj->stream_config.codec.aac_enc.enc_cfg),
+                   size_aac_cfg);
+            break;
+        }
+
+        default:
+            ret = -EINVAL;
+            goto err;
+            break;
+    }
+
+    header = (struct apm_module_param_data_t *)(payload);
+    header->module_instance_id = mod->miid;
+    header->param_id = PARAM_ID_ENCODER_OUTPUT_CONFIG;
+    header->error_code = 0x0;
+    header->param_size = sizeof(struct param_id_encoder_output_config_t);
+
+    ret = gsl_set_custom_config(graph_obj->graph_handle, payload, payload_size);
+    if (ret != 0) {
+        ret = ar_err_get_lnx_err_code(ret);
+        AGM_LOGE(
+            "custom_config command for module %d with "
+            "PARAM_ID_ENCODER_OUTPUT_CONFIG failed with error %d",
+            mod->tag, ret);
+        goto err;
+    } else {
+        struct aac_enc_cfg_t *aac_cfg =
+            (struct aac_enc_cfg_t *)(payload + size_apm_and_encoder_config);
+        AGM_LOGD("AAC encode mode: 0x%x, fmt_flag: 0x%x", aac_cfg->enc_mode,
+                 aac_cfg->aac_fmt_flag);
+        free(payload);
+        payload = NULL;
+    }
+
+    /**
+     * For Encoder Module, PARAM_ID_ENC_BITRATE
+     * */
+    switch (sess_obj->in_media_config.format) {
+        case AGM_FORMAT_AAC: {
+            struct param_id_enc_bitrate_param_t *bitrate_param = NULL;
+            size_t bitrate_param_size =
+                sizeof(struct param_id_enc_bitrate_param_t);
+            payload_size = size_apm_module + bitrate_param_size;
+            /*ensure that the payloadszie is byte multiple atleast*/
+            ALIGN_PAYLOAD(payload_size, 8);
+            payload = (uint8_t *)calloc(1, payload_size);
+            if (!payload) {
+                AGM_LOGE("Not enough memory for payload");
+                ret = -ENOMEM;
+                goto err;
+            }
+
+            bitrate_param =
+                (struct param_id_enc_bitrate_param_t *)(payload +
+                                                        size_apm_module);
+            bitrate_param->bitrate =
+                sess_obj->stream_config.codec.aac_enc.aac_bit_rate;
+            break;
+        }
+
+        default:
+            ret = -EINVAL;
+            goto err;
+            break;
+    }
+    header = (struct apm_module_param_data_t *)(payload);
+    header->module_instance_id = mod->miid;
+    header->param_id = PARAM_ID_ENC_BITRATE;
+    header->error_code = 0x0;
+    header->param_size = sizeof(struct param_id_enc_bitrate_param_t);
+
+    ret = gsl_set_custom_config(graph_obj->graph_handle, payload, payload_size);
+    if (ret != 0) {
+        ret = ar_err_get_lnx_err_code(ret);
+        AGM_LOGE(
+            "custom_config command for module %d with "
+            "PARAM_ID_ENC_BITRATE failed with error %d",
+            mod->tag, ret);
+        goto err;
+    } else {
+        struct param_id_enc_bitrate_param_t *bitrate_param =
+            (struct param_id_enc_bitrate_param_t *)(payload + size_apm_module);
+        AGM_LOGD("AAC bitrate: %d", bitrate_param->bitrate);
+        free(payload);
+        payload = NULL;
+    }
+
+err:
+done:
+    if (payload) {
+        free(payload);
+        payload = NULL;
+    }
+    AGM_LOGV("Exit: %d", ret);
+    return ret;
+}
+
+/**
  *Configure placeholder encoder
 */
 int configure_placeholder_enc(struct module_info *mod,
@@ -1282,6 +1459,14 @@
     }
     sess_obj = graph_obj->sess_obj;
 
+    /* configure only in case of compress capture */
+    if (sess_obj->stream_config.sess_mode == AGM_SESSION_COMPRESS &&
+        sess_obj->stream_config.dir == TX) {
+        ret = configure_encoder_output_media_format(mod, graph_obj);
+        if (ret != 0)
+            AGM_LOGE("configure_encoder_output_media_format failed: %d", ret);
+    }
+
     /* 1. Configure placeholder encoder with Real ID */
     ret = get_media_fmt_id_and_size(sess_obj->in_media_config.format,
                                     &payload_size, &real_fmt_id);
@@ -1590,14 +1775,18 @@
     uint8_t *payload = NULL;
     size_t payload_size = 0;
 
+    AGM_LOGD("Enter");
+
     /*
-     *Note: read shared mem ep is configured only in case of non-tunnel
+     *Note: read shared mem ep is configured in case of non-tunnel
      *decode sessions where the client has configured the session with
      *AGM_SESSION_FLAG_INBAND_SRCM flag
      *In case of non-tunnel encode sessions, we set the num_frames_per_buff cfg
      *as a part of calibration itself.
+     *In case of compress capture case also , read shared mem ep is configured.
      */
-    if (!(sess_obj->stream_config.sess_flags & AGM_SESSION_FLAG_INBAND_SRCM))
+    if (!(sess_obj->stream_config.sess_flags & AGM_SESSION_FLAG_INBAND_SRCM) &&
+        !(sess_obj->stream_config.sess_mode == AGM_SESSION_COMPRESS))
         goto done;
 
     AGM_LOGD("entry mod tag %x miid %x mid %x sess_flags %x",mod->tag, mod->miid, mod->mid,
@@ -1630,16 +1819,25 @@
      *In NT mode session in_media config represents config for data being captured
      *Hence for NT Mode decode it would mean PCM data.
      */
-    if (is_format_pcm(sess_obj->in_media_config.format))
-       rd_sh_mem_cfg->num_frames_per_buffer = 0x0; /*As many frames as possible*/
-    else
-       /*TODO:This is encode usecase hence ideally client wont enable SRCM event
-        *Even if the client wants it enabled, then we configure 1 frame every for
-        *every read call;
-        */
-       rd_sh_mem_cfg->num_frames_per_buffer = 0x1;
+    if (sess_obj->stream_config.sess_mode == AGM_SESSION_NON_TUNNEL) {
+        rd_sh_mem_cfg->metadata_control_flags = 0x2; /*ENABLE_MEDIA_FORMAT_MD*/
+        if (is_format_pcm(sess_obj->in_media_config.format))
+            rd_sh_mem_cfg->num_frames_per_buffer = 0x0; /*As many frames as possible*/
+        else
+        /*TODO:This is encode usecase hence ideally client wont enable SRCM event
+            *Even if the client wants it enabled, then we configure 1 frame every for
+            *every read call;
+            */
+            rd_sh_mem_cfg->num_frames_per_buffer = 0x1;
+    }
 
-    rd_sh_mem_cfg->metadata_control_flags = 0x2; /*ENABLE_MEDIA_FORMAT_MD*/
+    /* For compress capture */
+    if (sess_obj->stream_config.sess_mode == AGM_SESSION_COMPRESS &&
+        sess_obj->stream_config.dir == TX) {
+        rd_sh_mem_cfg->num_frames_per_buffer = 0x1;
+        AGM_LOGD("compress capture uses 1 frame per buffer");
+    }
+
 
     ret = gsl_set_custom_config(graph_obj->graph_handle, payload, payload_size);
     if (ret != 0) {