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 = ¶ms->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) {