Merge "hal: Add property to configure the compress offload fragment size."
diff --git a/hal/Android.mk b/hal/Android.mk
index d8a4733..037be56 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -62,6 +62,7 @@
LOCAL_CFLAGS += -DMULTI_VOICE_SESSION_ENABLED
LOCAL_SRC_FILES += voice_extn/voice_extn.c
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+ LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
ifneq ($(strip $(AUDIO_FEATURE_DISABLED_INCALL_MUSIC)),true)
LOCAL_CFLAGS += -DINCALL_MUSIC_ENABLED
@@ -78,6 +79,7 @@
LOCAL_CFLAGS += -DSPKR_PROT_ENABLED
LOCAL_SRC_FILES += audio_extn/spkr_protection.c
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+ LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
endif
endif
@@ -94,6 +96,7 @@
ifneq ($(strip $(AUDIO_FEATURE_DISABLED_DS1_DOLBY_DDP)),true)
LOCAL_CFLAGS += -DDS1_DOLBY_DDP_ENABLED
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+ LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
endif
LOCAL_SHARED_LIBRARIES := \
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index 72e2f9c..3f457d2 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -119,18 +119,18 @@
aextnmod.anc_enabled = true;
else
aextnmod.anc_enabled = false;
- }
- list_for_each(node, &adev->usecase_list) {
- usecase = node_to_item(node, struct audio_usecase, list);
- if (usecase->type == PCM_PLAYBACK) {
- if (usecase->stream.out->devices == \
- AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
- usecase->stream.out->devices == \
- AUDIO_DEVICE_OUT_WIRED_HEADSET) {
- select_devices(adev, usecase->id);
- ALOGV("%s: switching device", __func__);
- break;
+ list_for_each(node, &adev->usecase_list) {
+ usecase = node_to_item(node, struct audio_usecase, list);
+ if (usecase->type == PCM_PLAYBACK) {
+ if (usecase->stream.out->devices == \
+ AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
+ usecase->stream.out->devices == \
+ AUDIO_DEVICE_OUT_WIRED_HEADSET) {
+ select_devices(adev, usecase->id);
+ ALOGV("%s: switching device", __func__);
+ break;
+ }
}
}
}
@@ -143,6 +143,77 @@
#define audio_extn_set_afe_proxy_parameters(parms) (0)
#define audio_extn_get_afe_proxy_parameters(query, reply) (0)
#else
+/* Front left channel. */
+#define PCM_CHANNEL_FL 1
+
+/* Front right channel. */
+#define PCM_CHANNEL_FR 2
+
+/* Front center channel. */
+#define PCM_CHANNEL_FC 3
+
+/* Left surround channel.*/
+#define PCM_CHANNEL_LS 4
+
+/* Right surround channel.*/
+#define PCM_CHANNEL_RS 5
+
+/* Low frequency effect channel. */
+#define PCM_CHANNEL_LFE 6
+
+/* Left back channel; Rear left channel. */
+#define PCM_CHANNEL_LB 8
+
+/* Right back channel; Rear right channel. */
+#define PCM_CHANNEL_RB 9
+
+static int32_t afe_proxy_set_channel_mapping(struct audio_device *adev,
+ int channel_count)
+{
+ struct mixer_ctl *ctl;
+ const char *mixer_ctl_name = "Playback Channel Map";
+ int set_values[8] = {0};
+ int ret;
+ ALOGV("%s channel_count:%d",__func__, channel_count);
+
+ switch (channel_count) {
+ case 6:
+ set_values[0] = PCM_CHANNEL_FL;
+ set_values[1] = PCM_CHANNEL_FR;
+ set_values[2] = PCM_CHANNEL_FC;
+ set_values[3] = PCM_CHANNEL_LFE;
+ set_values[4] = PCM_CHANNEL_LS;
+ set_values[5] = PCM_CHANNEL_RS;
+ break;
+ case 8:
+ set_values[0] = PCM_CHANNEL_FL;
+ set_values[1] = PCM_CHANNEL_FR;
+ set_values[2] = PCM_CHANNEL_FC;
+ set_values[3] = PCM_CHANNEL_LFE;
+ set_values[4] = PCM_CHANNEL_LS;
+ set_values[5] = PCM_CHANNEL_RS;
+ set_values[6] = PCM_CHANNEL_LB;
+ set_values[7] = PCM_CHANNEL_RB;
+ break;
+ default:
+ ALOGE("unsupported channels(%d) for setting channel map",
+ channel_count);
+ return -EINVAL;
+ }
+
+ ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s",
+ __func__, mixer_ctl_name);
+ return -EINVAL;
+ }
+ ALOGV("AFE: set mapping(%d %d %d %d %d %d %d %d) for channel:%d",
+ set_values[0], set_values[1], set_values[2], set_values[3], set_values[4],
+ set_values[5], set_values[6], set_values[7], channel_count);
+ ret = mixer_ctl_set_array(ctl, set_values, channel_count);
+ return ret;
+}
+
int32_t audio_extn_set_afe_proxy_channel_mixer(struct audio_device *adev)
{
int32_t ret = 0;
@@ -150,7 +221,6 @@
struct mixer_ctl *ctl = NULL;
const char *mixer_ctl_name = "PROXY_RX Channels";
-
ALOGD("%s: entry", __func__);
/* use the existing channel count set by hardware params to
configure the back end for stereo as usb/a2dp would be
@@ -177,6 +247,11 @@
}
mixer_ctl_set_enum_by_string(ctl, channel_cnt_str);
+ if (aextnmod.proxy_channel_num == 6 ||
+ aextnmod.proxy_channel_num == 8)
+ ret = afe_proxy_set_channel_mapping(adev,
+ aextnmod.proxy_channel_num);
+
ALOGD("%s: exit", __func__);
return ret;
}
@@ -215,6 +290,34 @@
return 0;
}
+
+/* must be called with hw device mutex locked */
+int32_t audio_extn_read_afe_proxy_channel_masks(struct stream_out *out)
+{
+ int ret = 0;
+ int channels = aextnmod.proxy_channel_num;
+
+ switch (channels) {
+ /*
+ * Do not handle stereo output in Multi-channel cases
+ * Stereo case is handled in normal playback path
+ */
+ case 6:
+ ALOGV("%s: AFE PROXY supports 5.1", __func__);
+ out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
+ break;
+ case 8:
+ ALOGV("%s: AFE PROXY supports 5.1 and 7.1 channels", __func__);
+ out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
+ out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
+ break;
+ default:
+ ALOGE("AFE PROXY does not support multi channel playback");
+ ret = -ENOSYS;
+ break;
+ }
+ return ret;
+}
#endif /* AFE_PROXY_ENABLED */
void audio_extn_set_parameters(struct audio_device *adev,
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index e6db5c1..6bd03ee 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -41,8 +41,10 @@
#ifndef AFE_PROXY_ENABLED
#define audio_extn_set_afe_proxy_channel_mixer(adev) (0)
+#define audio_extn_read_afe_proxy_channel_masks(out) (0)
#else
int32_t audio_extn_set_afe_proxy_channel_mixer(struct audio_device *adev);
+int32_t audio_extn_read_afe_proxy_channel_masks(struct stream_out *out);
#endif
#ifndef USB_HEADSET_ENABLED
@@ -94,14 +96,11 @@
#endif
#ifndef AUDIO_LISTEN_ENABLED
-
#define audio_extn_listen_init(adev, snd_card) (0)
#define audio_extn_listen_deinit(adev) (0)
#define audio_extn_listen_update_status(uc_info, event) (0)
#define audio_extn_listen_set_parameters(adev, parms) (0)
-
#else
-
enum listen_event_type {
LISTEN_EVENT_SND_DEVICE_FREE,
LISTEN_EVENT_SND_DEVICE_BUSY
@@ -114,11 +113,10 @@
listen_event_type_t event);
void audio_extn_listen_set_parameters(struct audio_device *adev,
struct str_parms *parms);
-
#endif /* AUDIO_LISTEN_ENABLED */
#ifndef AUXPCM_BT_ENABLED
-#define audio_extn_read_xml(adev, MIXER_CARD, MIXER_XML_PATH, \
+#define audio_extn_read_xml(adev, mixer_card, MIXER_XML_PATH, \
MIXER_XML_PATH_AUXPCM) (-ENOSYS)
#else
int32_t audio_extn_read_xml(struct audio_device *adev, uint32_t mixer_card,
diff --git a/hal/audio_extn/compress_capture.c b/hal/audio_extn/compress_capture.c
index f3db419..0a2de36 100644
--- a/hal/audio_extn/compress_capture.c
+++ b/hal/audio_extn/compress_capture.c
@@ -93,7 +93,10 @@
bool audio_extn_compr_cap_usecase_supported(audio_usecase_t usecase)
{
- if (usecase == USECASE_AUDIO_RECORD_COMPRESS)
+ if ((usecase == USECASE_AUDIO_RECORD_COMPRESS) ||
+ (usecase == USECASE_INCALL_REC_UPLINK_COMPRESS) ||
+ (usecase == USECASE_INCALL_REC_DOWNLINK_COMPRESS) ||
+ (usecase == USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS))
return true;
else
return false;
diff --git a/hal/audio_extn/fm.c b/hal/audio_extn/fm.c
index eeba404..a4157f8 100644
--- a/hal/audio_extn/fm.c
+++ b/hal/audio_extn/fm.c
@@ -170,10 +170,10 @@
__func__, pcm_dev_rx_id, pcm_dev_tx_id, uc_info->id);
ALOGV("%s: Opening PCM playback device card_id(%d) device_id(%d)",
- __func__, SOUND_CARD, pcm_dev_rx_id);
- fmmod.fm_pcm_rx = pcm_open(SOUND_CARD,
- pcm_dev_rx_id,
- PCM_OUT, &pcm_config_fm);
+ __func__, adev->snd_card, pcm_dev_rx_id);
+ fmmod.fm_pcm_rx = pcm_open(adev->snd_card,
+ pcm_dev_rx_id,
+ PCM_OUT, &pcm_config_fm);
if (fmmod.fm_pcm_rx && !pcm_is_ready(fmmod.fm_pcm_rx)) {
ALOGE("%s: %s", __func__, pcm_get_error(fmmod.fm_pcm_rx));
ret = -EIO;
@@ -181,10 +181,10 @@
}
ALOGV("%s: Opening PCM capture device card_id(%d) device_id(%d)",
- __func__, SOUND_CARD, pcm_dev_tx_id);
- fmmod.fm_pcm_tx = pcm_open(SOUND_CARD,
- pcm_dev_tx_id,
- PCM_IN, &pcm_config_fm);
+ __func__, adev->snd_card, pcm_dev_tx_id);
+ fmmod.fm_pcm_tx = pcm_open(adev->snd_card,
+ pcm_dev_tx_id,
+ PCM_IN, &pcm_config_fm);
if (fmmod.fm_pcm_tx && !pcm_is_ready(fmmod.fm_pcm_tx)) {
ALOGE("%s: %s", __func__, pcm_get_error(fmmod.fm_pcm_tx));
ret = -EIO;
diff --git a/hal/audio_extn/hfp.c b/hal/audio_extn/hfp.c
index 73824bd..6b0546a 100644
--- a/hal/audio_extn/hfp.c
+++ b/hal/audio_extn/hfp.c
@@ -43,10 +43,10 @@
#ifdef HFP_ENABLED
#define AUDIO_PARAMETER_HFP_ENABLE "hfp_enable"
-static int32_t audio_extn_start_hfp(struct audio_device *adev,
+static int32_t start_hfp(struct audio_device *adev,
struct str_parms *parms);
-static int32_t audio_extn_stop_hfp(struct audio_device *adev);
+static int32_t stop_hfp(struct audio_device *adev);
struct hfp_module {
struct pcm *hfp_sco_rx;
@@ -76,22 +76,7 @@
.avail_min = 0,
};
-void audio_extn_hfp_set_parameters(struct audio_device *adev, struct str_parms *parms)
-{
- int ret;
- char value[32]={0};
-
- ret = str_parms_get_str(parms, AUDIO_PARAMETER_HFP_ENABLE, value,
- sizeof(value));
- if (ret >= 0) {
- if(!strncmp(value,"true",sizeof(value)))
- ret = audio_extn_start_hfp(adev,parms);
- else
- audio_extn_stop_hfp(adev);
- }
-}
-
-static int32_t audio_extn_start_hfp(struct audio_device *adev,
+static int32_t start_hfp(struct audio_device *adev,
struct str_parms *parms)
{
int32_t i, ret = 0;
@@ -128,8 +113,8 @@
__func__, pcm_dev_rx_id, pcm_dev_tx_id, uc_info->id);
ALOGV("%s: Opening PCM playback device card_id(%d) device_id(%d)",
- __func__, SOUND_CARD, pcm_dev_rx_id);
- hfpmod.hfp_sco_rx = pcm_open(SOUND_CARD,
+ __func__, adev->snd_card, pcm_dev_rx_id);
+ hfpmod.hfp_sco_rx = pcm_open(adev->snd_card,
pcm_dev_asm_rx_id,
PCM_OUT, &pcm_config_hfp);
if (hfpmod.hfp_sco_rx && !pcm_is_ready(hfpmod.hfp_sco_rx)) {
@@ -138,8 +123,8 @@
goto exit;
}
ALOGD("%s: Opening PCM capture device card_id(%d) device_id(%d)",
- __func__, SOUND_CARD, pcm_dev_tx_id);
- hfpmod.hfp_pcm_rx = pcm_open(SOUND_CARD,
+ __func__, adev->snd_card, pcm_dev_tx_id);
+ hfpmod.hfp_pcm_rx = pcm_open(adev->snd_card,
pcm_dev_rx_id,
PCM_OUT, &pcm_config_hfp);
if (hfpmod.hfp_pcm_rx && !pcm_is_ready(hfpmod.hfp_pcm_rx)) {
@@ -147,7 +132,7 @@
ret = -EIO;
goto exit;
}
- hfpmod.hfp_sco_tx = pcm_open(SOUND_CARD,
+ hfpmod.hfp_sco_tx = pcm_open(adev->snd_card,
pcm_dev_asm_tx_id,
PCM_IN, &pcm_config_hfp);
if (hfpmod.hfp_sco_tx && !pcm_is_ready(hfpmod.hfp_sco_tx)) {
@@ -156,8 +141,8 @@
goto exit;
}
ALOGV("%s: Opening PCM capture device card_id(%d) device_id(%d)",
- __func__, SOUND_CARD, pcm_dev_tx_id);
- hfpmod.hfp_pcm_tx = pcm_open(SOUND_CARD,
+ __func__, adev->snd_card, pcm_dev_tx_id);
+ hfpmod.hfp_pcm_tx = pcm_open(adev->snd_card,
pcm_dev_tx_id,
PCM_IN, &pcm_config_hfp);
if (hfpmod.hfp_pcm_tx && !pcm_is_ready(hfpmod.hfp_pcm_tx)) {
@@ -177,12 +162,12 @@
return 0;
exit:
- audio_extn_stop_hfp(adev);
+ stop_hfp(adev);
ALOGE("%s: Problem in HFP start: status(%d)", __func__, ret);
return ret;
}
-static int32_t audio_extn_stop_hfp(struct audio_device *adev)
+static int32_t stop_hfp(struct audio_device *adev)
{
int32_t i, ret = 0;
struct audio_usecase *uc_info;
@@ -228,4 +213,19 @@
ALOGD("%s: exit: status(%d)", __func__, ret);
return ret;
}
+
+void audio_extn_hfp_set_parameters(struct audio_device *adev, struct str_parms *parms)
+{
+ int ret;
+ char value[32]={0};
+
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_HFP_ENABLE, value,
+ sizeof(value));
+ if (ret >= 0) {
+ if(!strncmp(value,"true",sizeof(value)))
+ ret = start_hfp(adev,parms);
+ else
+ stop_hfp(adev);
+ }
+}
#endif /*HFP_ENABLED*/
diff --git a/hal/audio_extn/listen.c b/hal/audio_extn/listen.c
index 65c0ae6..9166f8e 100644
--- a/hal/audio_extn/listen.c
+++ b/hal/audio_extn/listen.c
@@ -119,6 +119,12 @@
void audio_extn_listen_set_parameters(struct audio_device *adev,
struct str_parms *parms)
{
+ ALOGV("%s: enter: %s", __func__, str_parms_to_str(parms));
+
+ if (listen_dev) {
+ listen_dev->listen_set_parameters(&adev->device, str_parms_to_str(parms));
+ }
+
return;
}
diff --git a/hal/audio_extn/spkr_protection.c b/hal/audio_extn/spkr_protection.c
index 0fc790a..5ec7eba 100644
--- a/hal/audio_extn/spkr_protection.c
+++ b/hal/audio_extn/spkr_protection.c
@@ -240,8 +240,9 @@
goto exit;
}
handle.pcm_rx = handle.pcm_tx = NULL;
- handle.pcm_rx = pcm_open(SOUND_CARD, pcm_dev_rx_id,
- PCM_OUT, &pcm_config_skr_prot);
+ handle.pcm_rx = pcm_open(adev->snd_card,
+ pcm_dev_rx_id,
+ PCM_OUT, &pcm_config_skr_prot);
if (handle.pcm_rx && !pcm_is_ready(handle.pcm_rx)) {
ALOGE("%s: %s", __func__, pcm_get_error(handle.pcm_rx));
status.status = -EIO;
@@ -267,8 +268,9 @@
status.status = -ENODEV;
goto exit;
}
- handle.pcm_tx = pcm_open(SOUND_CARD, pcm_dev_tx_id,
- PCM_IN, &pcm_config_skr_prot);
+ handle.pcm_tx = pcm_open(adev->snd_card,
+ pcm_dev_tx_id,
+ PCM_IN, &pcm_config_skr_prot);
if (handle.pcm_tx && !pcm_is_ready(handle.pcm_tx)) {
ALOGE("%s: %s", __func__, pcm_get_error(handle.pcm_tx));
status.status = -EIO;
@@ -618,8 +620,9 @@
ret = -ENODEV;
goto exit;
}
- handle.pcm_tx = pcm_open(SOUND_CARD, pcm_dev_tx_id,
- PCM_IN, &pcm_config_skr_prot);
+ handle.pcm_tx = pcm_open(adev->snd_card,
+ pcm_dev_tx_id,
+ PCM_IN, &pcm_config_skr_prot);
if (handle.pcm_tx && !pcm_is_ready(handle.pcm_tx)) {
ALOGE("%s: %s", __func__, pcm_get_error(handle.pcm_tx));
ret = -EIO;
diff --git a/hal/audio_extn/usb.c b/hal/audio_extn/usb.c
index 88af9be..88e3cad 100644
--- a/hal/audio_extn/usb.c
+++ b/hal/audio_extn/usb.c
@@ -348,7 +348,10 @@
usbmod->proxy_pcm_playback_handle = pcm_open(usbmod->proxy_card,
usbmod->proxy_device_id, PCM_IN |
PCM_MMAP | PCM_NOIRQ, &pcm_config_usbmod);
- if(!usbmod->proxy_pcm_playback_handle){
+ if(usbmod->proxy_pcm_playback_handle
+ && !pcm_is_ready(usbmod->proxy_pcm_playback_handle)){
+ pcm_close(usbmod->proxy_pcm_playback_handle);
+ usbmod->proxy_pcm_playback_handle = NULL;
proxy_open_retry_count--;
usleep(USB_PROXY_OPEN_WAIT_TIME * 1000);
ALOGE("%s: pcm_open for proxy failed retrying = %d",
@@ -463,7 +466,10 @@
usbmod->proxy_pcm_record_handle = pcm_open(usbmod->proxy_card,
usbmod->proxy_device_id, PCM_OUT |
PCM_MMAP | PCM_NOIRQ, &pcm_config_usbmod);
- if(!usbmod->proxy_pcm_record_handle){
+ if(usbmod->proxy_pcm_record_handle
+ && !pcm_is_ready(usbmod->proxy_pcm_record_handle)){
+ pcm_close(usbmod->proxy_pcm_record_handle);
+ usbmod->proxy_pcm_record_handle = NULL;
proxy_open_retry_count--;
usleep(USB_PROXY_OPEN_WAIT_TIME * 1000);
ALOGE("%s: pcm_open for proxy(recording) failed retrying = %d",
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index bc3cd0d..fefbfa4 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -61,6 +61,8 @@
#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
+#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
+
struct pcm_config pcm_config_deep_buffer = {
.channels = 2,
.rate = DEFAULT_OUTPUT_SAMPLING_RATE,
@@ -120,6 +122,10 @@
[USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
[USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
[USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
+ [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
+ [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
+ [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
+
[USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
[USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
[USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
@@ -393,12 +399,6 @@
}
}
- list_for_each(node, &adev->usecase_list) {
- usecase = node_to_item(node, struct audio_usecase, list);
- if (switch_device[usecase->id]) {
- enable_snd_device(adev, snd_device, false);
- }
- }
/* Make sure new snd device is enabled before re-routing the streams */
audio_route_update_mixer(adev->audio_route);
@@ -800,9 +800,10 @@
select_devices(adev, in->usecase);
ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
- __func__, SOUND_CARD, in->pcm_device_id, in->config.channels);
- in->pcm = pcm_open(SOUND_CARD, in->pcm_device_id,
- PCM_IN, &in->config);
+ __func__, adev->snd_card,
+ in->pcm_device_id, in->config.channels);
+ in->pcm = pcm_open(adev->snd_card,
+ in->pcm_device_id, PCM_IN, &in->config);
if (in->pcm && !pcm_is_ready(in->pcm)) {
ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
pcm_close(in->pcm);
@@ -855,9 +856,6 @@
struct stream_out *out = (struct stream_out *) context;
struct listnode *item;
- out->offload_state = OFFLOAD_STATE_IDLE;
- out->playback_started = 0;
-
setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
set_sched_policy(0, SP_FOREGROUND);
prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
@@ -1117,8 +1115,9 @@
ALOGV("%s: Opening PCM device card_id(%d) device_id(%d)",
__func__, 0, out->pcm_device_id);
if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
- out->pcm = pcm_open(SOUND_CARD, out->pcm_device_id,
- PCM_OUT | PCM_MONOTONIC, &out->config);
+ out->pcm = pcm_open(adev->snd_card,
+ out->pcm_device_id,
+ PCM_OUT | PCM_MONOTONIC, &out->config);
if (out->pcm && !pcm_is_ready(out->pcm)) {
ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
pcm_close(out->pcm);
@@ -1128,7 +1127,8 @@
}
} else {
out->pcm = NULL;
- out->compr = compress_open(SOUND_CARD, out->pcm_device_id,
+ out->compr = compress_open(adev->snd_card,
+ out->pcm_device_id,
COMPRESS_IN, &out->compr_config);
if (out->compr && !is_compress_ready(out->compr)) {
ALOGE("%s: %s", __func__, compress_get_error(out->compr));
@@ -1999,6 +1999,13 @@
*stream_out = NULL;
out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
+ if (!out) {
+ return -ENOMEM;
+ }
+
+ pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
+ pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
+
if (devices == AUDIO_DEVICE_NONE)
devices = AUDIO_DEVICE_OUT_SPEAKER;
@@ -2012,10 +2019,16 @@
out->handle = handle;
/* Init use case and pcm_config */
- if (out->flags == AUDIO_OUTPUT_FLAG_DIRECT &&
- out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
+ if ((out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
+ (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
+ out->devices & AUDIO_DEVICE_OUT_PROXY)) {
+
pthread_mutex_lock(&adev->lock);
- ret = read_hdmi_channel_masks(out);
+ if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
+ ret = read_hdmi_channel_masks(out);
+
+ if (out->devices & AUDIO_DEVICE_OUT_PROXY)
+ ret = audio_extn_read_afe_proxy_channel_masks(out);
pthread_mutex_unlock(&adev->lock);
if (ret != 0)
goto error_open;
@@ -2092,6 +2105,9 @@
out->non_blocking = 1;
out->send_new_metadata = 1;
+ out->offload_state = OFFLOAD_STATE_IDLE;
+ out->playback_started = 0;
+
create_offload_callback_thread(out);
ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
__func__, config->offload_info.version,
@@ -2118,12 +2134,15 @@
out->config = pcm_config_low_latency;
out->sample_rate = out->config.rate;
} else {
- out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
+ /* primary path is the default path selected if no other outputs are available/suitable */
+ out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
out->config = pcm_config_deep_buffer;
out->sample_rate = out->config.rate;
}
- if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
+ if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
+ (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
+ /* Ensure the default output is not selected twice */
if(adev->primary_output == NULL)
adev->primary_output = out;
else {
@@ -2166,9 +2185,6 @@
/* out->muted = false; by calloc() */
/* out->written = 0; by calloc() */
- pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
- pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
-
config->format = out->stream.common.get_format(&out->stream.common);
config->channel_mask = out->stream.common.get_channels(&out->stream.common);
config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
@@ -2588,6 +2604,7 @@
free(adev);
ALOGE("%s: Failed to init platform data, aborting.", __func__);
*device = NULL;
+ pthread_mutex_unlock(&adev_init_lock);
return -EINVAL;
}
@@ -2605,7 +2622,7 @@
"visualizer_hal_stop_output");
}
}
- audio_extn_listen_init(adev, SOUND_CARD);
+ audio_extn_listen_init(adev, adev->snd_card);
if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
@@ -2666,7 +2683,7 @@
.hal_api_version = HARDWARE_HAL_API_VERSION,
.id = AUDIO_HARDWARE_MODULE_ID,
.name = "QCOM Audio HAL",
- .author = "Code Aurora Forum",
+ .author = "The Linux Foundation",
.methods = &hal_module_methods,
},
};
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index d23c184..73575e8 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -84,6 +84,9 @@
USECASE_INCALL_REC_UPLINK,
USECASE_INCALL_REC_DOWNLINK,
USECASE_INCALL_REC_UPLINK_AND_DOWNLINK,
+ USECASE_INCALL_REC_UPLINK_COMPRESS,
+ USECASE_INCALL_REC_DOWNLINK_COMPRESS,
+ USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS,
USECASE_INCALL_MUSIC_UPLINK,
USECASE_INCALL_MUSIC_UPLINK2,
@@ -220,6 +223,7 @@
struct voice voice;
unsigned int cur_hdmi_channels;
+ int snd_card;
void *platform;
void *visualizer_lib;
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 25f52d6..272dea8 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -53,6 +53,7 @@
/* Retry for delay in FW loading*/
#define RETRY_NUMBER 10
#define RETRY_US 500000
+#define MAX_SND_CARD 8
#define SAMPLE_RATE_8KHZ 8000
#define SAMPLE_RATE_16KHZ 16000
@@ -121,6 +122,12 @@
AUDIO_RECORD_PCM_DEVICE},
[USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = {AUDIO_RECORD_PCM_DEVICE,
AUDIO_RECORD_PCM_DEVICE},
+ [USECASE_INCALL_REC_UPLINK_COMPRESS] = {COMPRESS_CAPTURE_DEVICE,
+ COMPRESS_CAPTURE_DEVICE},
+ [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = {COMPRESS_CAPTURE_DEVICE,
+ COMPRESS_CAPTURE_DEVICE},
+ [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = {COMPRESS_CAPTURE_DEVICE,
+ COMPRESS_CAPTURE_DEVICE},
[USECASE_INCALL_MUSIC_UPLINK] = {INCALL_MUSIC_UPLINK_PCM_DEVICE,
INCALL_MUSIC_UPLINK_PCM_DEVICE},
[USECASE_INCALL_MUSIC_UPLINK2] = {INCALL_MUSIC_UPLINK2_PCM_DEVICE,
@@ -422,38 +429,58 @@
char platform[PROPERTY_VALUE_MAX];
char baseband[PROPERTY_VALUE_MAX];
char value[PROPERTY_VALUE_MAX];
- struct platform_data *my_data;
- int retry_num = 0;
+ struct platform_data *my_data = NULL;
+ int retry_num = 0, snd_card_num = 0;
const char *snd_card_name;
- adev->mixer = mixer_open(MIXER_CARD);
-
- while (!adev->mixer && retry_num < RETRY_NUMBER) {
- usleep(RETRY_US);
- adev->mixer = mixer_open(MIXER_CARD);
- retry_num++;
- }
-
- if (!adev->mixer) {
- ALOGE("Unable to open the mixer, aborting.");
- return NULL;
- }
-
- if (audio_extn_read_xml(adev, MIXER_CARD, MIXER_XML_PATH,
- MIXER_XML_PATH_AUXPCM) == -ENOSYS)
- adev->audio_route = audio_route_init(MIXER_CARD, MIXER_XML_PATH);
-
- if (!adev->audio_route) {
- ALOGE("%s: Failed to init audio route controls, aborting.", __func__);
- return NULL;
- }
-
my_data = calloc(1, sizeof(struct platform_data));
- snd_card_name = mixer_get_name(adev->mixer);
- my_data->hw_info = hw_info_init(snd_card_name);
- if (!my_data->hw_info) {
- ALOGE("%s: Failed to init hardware info", __func__);
+ while (snd_card_num < MAX_SND_CARD) {
+ adev->mixer = mixer_open(snd_card_num);
+
+ while (!adev->mixer && retry_num < RETRY_NUMBER) {
+ usleep(RETRY_US);
+ adev->mixer = mixer_open(snd_card_num);
+ retry_num++;
+ }
+
+ if (!adev->mixer) {
+ ALOGE("%s: Unable to open the mixer card: %d", __func__,
+ snd_card_num);
+ retry_num = 0;
+ snd_card_num++;
+ continue;
+ }
+
+ snd_card_name = mixer_get_name(adev->mixer);
+ ALOGV("%s: snd_card_name: %s", __func__, snd_card_name);
+
+ my_data->hw_info = hw_info_init(snd_card_name);
+ if (!my_data->hw_info) {
+ ALOGE("%s: Failed to init hardware info", __func__);
+ } else {
+ if (audio_extn_read_xml(adev, snd_card_num, MIXER_XML_PATH,
+ MIXER_XML_PATH_AUXPCM) == -ENOSYS)
+ adev->audio_route = audio_route_init(snd_card_num,
+ MIXER_XML_PATH);
+ if (!adev->audio_route) {
+ ALOGE("%s: Failed to init audio route controls, aborting.",
+ __func__);
+ free(my_data);
+ return NULL;
+ }
+ adev->snd_card = snd_card_num;
+ ALOGD("%s: Opened sound card:%d", __func__, snd_card_num);
+ break;
+ }
+ retry_num = 0;
+ snd_card_num++;
+ }
+
+ if (snd_card_num >= MAX_SND_CARD) {
+ ALOGE("%s: Unable to find correct sound card, aborting.", __func__);
+ free(my_data);
+ return NULL;
}
my_data->adev = adev;
@@ -530,6 +557,8 @@
/* init usb */
audio_extn_usb_init(adev);
+ /* update sound cards appropriately */
+ audio_extn_usb_set_proxy_sound_card(adev->snd_card);
/* Read one time ssr property */
audio_extn_ssr_update_enabled(adev);
@@ -986,7 +1015,7 @@
} else if (my_data->fluence_type == FLUENCE_NONE ||
my_data->fluence_in_voice_call == false) {
snd_device = SND_DEVICE_IN_HANDSET_MIC;
- set_echo_reference(adev->mixer, "SLIM_RX");
+ set_echo_reference(adev->mixer, EC_REF_RX);
} else {
snd_device = SND_DEVICE_IN_VOICE_DMIC;
adev->acdb_settings |= DMIC_FLAG;
@@ -1055,7 +1084,7 @@
} else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
}
- set_echo_reference(adev->mixer, "SLIM_RX");
+ set_echo_reference(adev->mixer, EC_REF_RX);
} else if (adev->active_input->enable_aec) {
if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
@@ -1072,7 +1101,7 @@
} else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
}
- set_echo_reference(adev->mixer, "SLIM_RX");
+ set_echo_reference(adev->mixer, EC_REF_RX);
} else if (adev->active_input->enable_ns) {
if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 8518c7d..e7980d6 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -126,9 +126,6 @@
};
-#define MIXER_CARD 0
-#define SOUND_CARD 0
-
#define DEFAULT_OUTPUT_SAMPLING_RATE 48000
#define ALL_SESSION_VSID 0xFFFFFFFF
@@ -171,8 +168,8 @@
#define FM_PLAYBACK_PCM_DEVICE 5
#define FM_CAPTURE_PCM_DEVICE 6
#define HFP_PCM_RX 5
-#define HFP_SCO_RX 35
-#define HFP_ASM_RX_TX 36
+#define HFP_SCO_RX 23
+#define HFP_ASM_RX_TX 24
#define INCALL_MUSIC_UPLINK_PCM_DEVICE 1
#define INCALL_MUSIC_UPLINK2_PCM_DEVICE 16
@@ -183,8 +180,10 @@
#ifdef PLATFORM_MSM8610
#define LOWLATENCY_PCM_DEVICE 12
+#define EC_REF_RX "I2S_RX"
#else
#define LOWLATENCY_PCM_DEVICE 15
+#define EC_REF_RX "SLIM_RX"
#endif
#ifdef PLATFORM_MSM8x26
#define COMPRESS_CAPTURE_DEVICE 20
@@ -202,11 +201,16 @@
#define VOICE2_CALL_PCM_DEVICE 13
#define VOLTE_CALL_PCM_DEVICE 21
#define QCHAT_CALL_PCM_DEVICE 06
-#else
+#elif PLATFORM_MSM8610
#define VOICE_CALL_PCM_DEVICE 2
#define VOICE2_CALL_PCM_DEVICE 13
#define VOLTE_CALL_PCM_DEVICE 14
#define QCHAT_CALL_PCM_DEVICE 20
+#else
+#define VOICE_CALL_PCM_DEVICE 2
+#define VOICE2_CALL_PCM_DEVICE 22
+#define VOLTE_CALL_PCM_DEVICE 14
+#define QCHAT_CALL_PCM_DEVICE 20
#endif
#define LIB_CSD_CLIENT "libcsd-client.so"
diff --git a/hal/voice.c b/hal/voice.c
index 25b53d4..cbf8956 100644
--- a/hal/voice.c
+++ b/hal/voice.c
@@ -135,8 +135,8 @@
}
ALOGV("%s: Opening PCM playback device card_id(%d) device_id(%d)",
- __func__, SOUND_CARD, pcm_dev_rx_id);
- session->pcm_rx = pcm_open(SOUND_CARD,
+ __func__, adev->snd_card, pcm_dev_rx_id);
+ session->pcm_rx = pcm_open(adev->snd_card,
pcm_dev_rx_id,
PCM_OUT, &voice_config);
if (session->pcm_rx && !pcm_is_ready(session->pcm_rx)) {
@@ -146,8 +146,8 @@
}
ALOGV("%s: Opening PCM capture device card_id(%d) device_id(%d)",
- __func__, SOUND_CARD, pcm_dev_tx_id);
- session->pcm_tx = pcm_open(SOUND_CARD,
+ __func__, adev->snd_card, pcm_dev_tx_id);
+ session->pcm_tx = pcm_open(adev->snd_card,
pcm_dev_tx_id,
PCM_IN, &voice_config);
if (session->pcm_tx && !pcm_is_ready(session->pcm_tx)) {
@@ -212,15 +212,27 @@
if (voice_is_in_call(adev)) {
switch (in->source) {
case AUDIO_SOURCE_VOICE_UPLINK:
- in->usecase = USECASE_INCALL_REC_UPLINK;
+ if (audio_extn_compr_cap_enabled() &&
+ audio_extn_compr_cap_format_supported(in->config.format)) {
+ in->usecase = USECASE_INCALL_REC_UPLINK_COMPRESS;
+ } else
+ in->usecase = USECASE_INCALL_REC_UPLINK;
rec_mode = INCALL_REC_UPLINK;
break;
case AUDIO_SOURCE_VOICE_DOWNLINK:
- in->usecase = USECASE_INCALL_REC_DOWNLINK;
+ if (audio_extn_compr_cap_enabled() &&
+ audio_extn_compr_cap_format_supported(in->config.format)) {
+ in->usecase = USECASE_INCALL_REC_DOWNLINK_COMPRESS;
+ } else
+ in->usecase = USECASE_INCALL_REC_DOWNLINK;
rec_mode = INCALL_REC_DOWNLINK;
break;
case AUDIO_SOURCE_VOICE_CALL:
- in->usecase = USECASE_INCALL_REC_UPLINK_AND_DOWNLINK;
+ if (audio_extn_compr_cap_enabled() &&
+ audio_extn_compr_cap_format_supported(in->config.format)) {
+ in->usecase = USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS;
+ } else
+ in->usecase = USECASE_INCALL_REC_UPLINK_AND_DOWNLINK;
rec_mode = INCALL_REC_UPLINK_AND_DOWNLINK;
break;
default:
diff --git a/hal/voice_extn/compress_voip.c b/hal/voice_extn/compress_voip.c
index d5b0f0e..ee9fd30 100644
--- a/hal/voice_extn/compress_voip.c
+++ b/hal/voice_extn/compress_voip.c
@@ -348,8 +348,8 @@
}
ALOGD("%s: Opening PCM playback device card_id(%d) device_id(%d)",
- __func__, SOUND_CARD, pcm_dev_rx_id);
- voip_data.pcm_rx = pcm_open(SOUND_CARD,
+ __func__, adev->snd_card, pcm_dev_rx_id);
+ voip_data.pcm_rx = pcm_open(adev->snd_card,
pcm_dev_rx_id,
PCM_OUT, voip_config);
if (voip_data.pcm_rx && !pcm_is_ready(voip_data.pcm_rx)) {
@@ -361,8 +361,8 @@
}
ALOGD("%s: Opening PCM capture device card_id(%d) device_id(%d)",
- __func__, SOUND_CARD, pcm_dev_tx_id);
- voip_data.pcm_tx = pcm_open(SOUND_CARD,
+ __func__, adev->snd_card, pcm_dev_tx_id);
+ voip_data.pcm_tx = pcm_open(adev->snd_card,
pcm_dev_tx_id,
PCM_IN, voip_config);
if (voip_data.pcm_tx && !pcm_is_ready(voip_data.pcm_tx)) {
diff --git a/hal_mpq/Android.mk b/hal_mpq/Android.mk
index 683de7a..1cb7e60 100644
--- a/hal_mpq/Android.mk
+++ b/hal_mpq/Android.mk
@@ -44,9 +44,9 @@
$(call include-path-for, audio-effects) \
$(LOCAL_PATH)/$(AUDIO_PLATFORM)
-ifeq ($(strip $(AUDIO_FEATURE_ENABLED_AUXPCM_BT)),true)
- LOCAL_CFLAGS += -DAUXPCM_BT_ENABLED
-endif
+
+LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
LOCAL_MODULE := audio.primary.$(TARGET_BOARD_PLATFORM)
diff --git a/hal_mpq/audio_bitstream_sm.c b/hal_mpq/audio_bitstream_sm.c
index 9f2564d..d2e4e6e 100644
--- a/hal_mpq/audio_bitstream_sm.c
+++ b/hal_mpq/audio_bitstream_sm.c
@@ -26,7 +26,7 @@
#include <math.h>
#define LOG_TAG "AudioBitstreamStateMachine"
-//#define LOG_NDEBUG 0
+#define LOG_NDEBUG 0
#define LOG_NDDEBUG 0
#include <utils/Log.h>
@@ -36,7 +36,6 @@
#include <platform.h>
// ----------------------------------------------------------------------------
-
/*
Initialize all input and output pointers
Allocate twice the max buffer size of input and output for sufficient buffering
@@ -45,52 +44,62 @@
{
bstream->buffering_factor = buffering_factor;
bstream->buffering_factor_cnt = 0;
+ bstream->inp_buf_size = SAMPLES_PER_CHANNEL *
+ MAX_INPUT_CHANNELS_SUPPORTED*
+ (bstream->buffering_factor+1);
+ bstream->inp_buf = (char *)malloc( bstream->inp_buf_size);
- bstream->inp_buf=(char *)malloc(SAMPLES_PER_CHANNEL*
- MAX_INPUT_CHANNELS_SUPPORTED*
- (bstream->buffering_factor+1));
// multiplied by 2 to convert to bytes
if(bstream->inp_buf != NULL) {
bstream->inp_buf_curr_ptr = bstream->inp_buf;
bstream->inp_buf_write_ptr = bstream->inp_buf;
} else {
ALOGE("MS11 input buffer not allocated");
+ bstream->inp_buf_size = 0;
return 0;
}
- bstream->enc_out_buf =(char *)malloc(SAMPLES_PER_CHANNEL*
- MAX_INPUT_CHANNELS_SUPPORTED*
- FACTOR_FOR_BUFFERING);
+ bstream->enc_out_buf_size = SAMPLES_PER_CHANNEL * MAX_INPUT_CHANNELS_SUPPORTED*
+ FACTOR_FOR_BUFFERING;
+ bstream->enc_out_buf =(char *)malloc(bstream->enc_out_buf_size);
+
if(bstream->enc_out_buf) {
bstream->enc_out_buf_write_ptr = bstream->enc_out_buf;
} else {
ALOGE("MS11 Enc output buffer not allocated");
+ bstream->enc_out_buf_size = 0;
return 0;
}
- bstream->pcm_2_out_buf =(char *)malloc(SAMPLES_PER_CHANNEL*STEREO_CHANNELS *
- FACTOR_FOR_BUFFERING);
+ bstream->pcm_2_out_buf_size = SAMPLES_PER_CHANNEL*STEREO_CHANNELS *
+ FACTOR_FOR_BUFFERING;
+ bstream->pcm_2_out_buf =(char *)malloc(bstream->pcm_2_out_buf_size);
if(bstream->pcm_2_out_buf) {
bstream->pcm_2_out_buf_write_ptr = bstream->pcm_2_out_buf;
} else {
ALOGE("MS11 PCM2Ch output buffer not allocated");
+ bstream->pcm_2_out_buf_size = 0;
return 0;
}
- bstream->pcm_mch_out_buf =(char *)malloc(SAMPLES_PER_CHANNEL *
- MAX_OUTPUT_CHANNELS_SUPPORTED *
- FACTOR_FOR_BUFFERING);
+ bstream->pcm_mch_out_buf_size = SAMPLES_PER_CHANNEL * MAX_OUTPUT_CHANNELS_SUPPORTED *
+ FACTOR_FOR_BUFFERING;
+
+ bstream->pcm_mch_out_buf =(char *)malloc(bstream->pcm_mch_out_buf_size);
if(bstream->pcm_mch_out_buf) {
bstream->pcm_mch_out_buf_write_ptr = bstream->pcm_mch_out_buf;
} else {
ALOGE("MS11 PCMMCh output buffer not allocated");
+ bstream->pcm_mch_out_buf_size = 0;
return 0;
}
- bstream->passt_out_buf =(char *)malloc(SAMPLES_PER_CHANNEL *
+ bstream->passt_out_buf_size =SAMPLES_PER_CHANNEL *
MAX_INPUT_CHANNELS_SUPPORTED *
- FACTOR_FOR_BUFFERING);
+ FACTOR_FOR_BUFFERING;
+ bstream->passt_out_buf =(char *)malloc(bstream->passt_out_buf_size);
if(bstream->passt_out_buf) {
bstream->passt_out_buf_write_ptr = bstream->passt_out_buf;
} else {
ALOGE("MS11 Enc output buffer not allocated");
+ bstream->passt_out_buf_size = 0;
return 0;
}
return 1;
@@ -159,9 +168,8 @@
struct audio_bitstream_sm *bstream,
char *buf_ptr, size_t bytes)
{
- int32_t bufLen = SAMPLES_PER_CHANNEL*MAX_INPUT_CHANNELS_SUPPORTED*(bstream->buffering_factor+1);
// flush the input buffer if input is not consumed
- if( (bstream->inp_buf_write_ptr+bytes) > (bstream->inp_buf+bufLen) ) {
+ if( (bstream->inp_buf_write_ptr+bytes) > (bstream->inp_buf+bstream->inp_buf_size) ) {
ALOGE("Input bitstream is not consumed");
return;
}
@@ -226,6 +234,38 @@
return bstream->inp_buf_write_ptr;
}
+int audio_bitstream_set_input_buffer_ptr(
+ struct audio_bitstream_sm *bstream, int bytes)
+{
+ if(((bstream->inp_buf_curr_ptr + bytes) <=
+ (bstream->inp_buf + bstream->inp_buf_size)) &&
+ ((bstream->inp_buf_curr_ptr + bytes) >= bstream->inp_buf))
+
+ bstream->inp_buf_curr_ptr += bytes;
+ else {
+ ALOGE("Invalid input buffer size %d bytes", bytes);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int audio_bitstream_set_input_buffer_write_ptr(
+ struct audio_bitstream_sm *bstream, int bytes)
+{
+ if(((bstream->inp_buf_write_ptr + bytes) <=
+ (bstream->inp_buf + bstream->inp_buf_size)) &&
+ ((bstream->inp_buf_write_ptr + bytes) >= bstream->inp_buf))
+
+ bstream->inp_buf_write_ptr += bytes;
+ else {
+ ALOGE("Invalid input buffer size %d bytes", bytes);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/*
Get the output buffer start pointer to start rendering the pcm sampled to driver
*/
diff --git a/hal_mpq/audio_hw.h b/hal_mpq/audio_hw.h
index e1319a5..7814d95 100644
--- a/hal_mpq/audio_hw.h
+++ b/hal_mpq/audio_hw.h
@@ -24,7 +24,7 @@
#include <hardware/audio.h>
#include <tinyalsa/asoundlib.h>
#include <tinycompress/tinycompress.h>
-
+#include "sound/compress_params.h"
#include <audio_route/audio_route.h>
#define VISUALIZER_LIBRARY_PATH "/system/lib/soundfx/libqcomvisualizer.so"
@@ -45,6 +45,7 @@
#define DEFAULT_HDMI_OUT_CHANNELS 2
typedef int snd_device_t;
+#include <platform.h>
/* These are the supported use cases by the hardware.
* Each usecase is mapped to a specific PCM device.
@@ -56,11 +57,11 @@
USECASE_AUDIO_PLAYBACK_DEEP_BUFFER = 0,
USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
USECASE_AUDIO_PLAYBACK_MULTI_CH,
- USECASE_AUDIO_PLAYBACK_OFFLOAD,
-
- /* FM usecase */
USECASE_AUDIO_PLAYBACK_FM,
-
+ USECASE_AUDIO_PLAYBACK_OFFLOAD,
+ USECASE_AUDIO_PLAYBACK_OFFLOAD1,
+ USECASE_AUDIO_PLAYBACK_OFFLOAD2,
+ USECASE_AUDIO_PLAYBACK_OFFLOAD3,
/* Capture usecases */
USECASE_AUDIO_RECORD,
USECASE_AUDIO_RECORD_COMPRESS,
@@ -88,6 +89,28 @@
AUDIO_USECASE_MAX
} audio_usecase_t;
+typedef enum {
+ DEEP_BUFFER_PLAYBACK_STREAM = 0,
+ LOW_LATENCY_PLAYBACK_STREAM,
+ MCH_PCM_PLAYBACK_STREAM,
+ OFFLOAD_PLAYBACK_STREAM,
+ LOW_LATENCY_RECORD_STREAM,
+ RECORD_STREAM,
+ VOICE_CALL_STREAM
+} audio_usecase_stream_type_t;
+
+#define STRING_TO_ENUM(string) { #string, string }
+struct string_to_enum {
+ const char *name;
+ uint32_t value;
+};
+
+static const struct string_to_enum out_channels_name_to_enum_table[] = {
+ STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
+ STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
+ STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
+};
+
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
/*
@@ -118,14 +141,43 @@
int data[];
};
+struct alsa_handle {
+
+ struct listnode list;
+//Parameters of the stream
+ struct pcm *pcm;
+ struct pcm_config config;
+
+ struct compress *compr;
+ struct compr_config compr_config;
+
+ struct stream_out *out;
+
+ audio_usecase_t usecase;
+ int device_id;
+ unsigned int sample_rate;
+ audio_channel_mask_t channel_mask;
+ audio_format_t input_format;
+ audio_format_t output_format;
+ audio_devices_t devices;
+
+ route_format_t route_format;
+ int decoder_type;
+
+ bool cmd_pending ;
+};
+
struct stream_out {
struct audio_stream_out stream;
pthread_mutex_t lock; /* see note below on mutex acquisition order */
pthread_cond_t cond;
+ /* TODO remove this */
+ /*
struct pcm_config config;
struct compr_config compr_config;
struct pcm *pcm;
struct compress *compr;
+ */
int standby;
int pcm_device_id;
unsigned int sample_rate;
@@ -154,6 +206,54 @@
int send_new_metadata;
struct audio_device *dev;
+
+ /*devices configuration */
+ int left_volume;
+ int right_volume;
+ audio_usecase_stream_type_t uc_strm_type;
+ int hdmi_format;
+ int spdif_format;
+ int* device_formats; //TODO:Needs to come from AudioRutingManager
+ struct audio_config *config;
+
+ /* list of the session handles */
+ struct listnode session_list;
+
+ /* /MS11 instance */
+ int use_ms11_decoder;
+ void *ms11_decoder;
+ struct compr_config compr_config;
+
+ int channels;
+
+ /* Buffering utility */
+ struct audio_bitstream_sm *bitstrm;
+
+ int buffer_size;
+ int decoder_type;
+ bool dec_conf_set;
+ uint32_t min_bytes_req_to_dec;
+ bool is_m11_file_mode;
+ void *dec_conf_buf;
+ int32_t dec_conf_bufLength;
+ bool first_bitstrm_buf;
+
+ bool open_dec_route;
+ int dec_format_devices;
+ bool open_dec_mch_route;
+ int dec_mch_format_devices;
+ bool open_passt_route;
+ int passt_format_devices;
+ bool sw_open_trans_route;
+ int sw_trans_format_devices;
+ bool hw_open_trans_route;
+ int hw_trans_format_devices;
+ bool channel_status_set;
+ unsigned char channel_status[24];
+ int route_audio_to_a2dp;
+ int is_ms11_file_playback_mode;
+ char * write_temp_buf;
+ struct output_metadata output_meta_data;
};
struct stream_in {
@@ -194,6 +294,7 @@
snd_device_t out_snd_device;
snd_device_t in_snd_device;
union stream_ptr stream;
+ struct alsa_handle *handle;
};
struct audio_device {
@@ -225,6 +326,9 @@
[USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
[USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
[USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
+ [USECASE_AUDIO_PLAYBACK_OFFLOAD1] = "compress-offload-playback1",
+ [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
+ [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
[USECASE_AUDIO_RECORD] = "audio-record",
[USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
[USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
@@ -245,6 +349,7 @@
[USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
};
+
int adev_open_output_stream(struct audio_hw_device *dev,
audio_io_handle_t handle,
audio_devices_t devices,
diff --git a/hal_mpq/audio_stream_out.c b/hal_mpq/audio_stream_out.c
index 71eb2f1..7ef3255 100644
--- a/hal_mpq/audio_stream_out.c
+++ b/hal_mpq/audio_stream_out.c
@@ -49,12 +49,24 @@
#include <platform.h>
#include "sound/compress_params.h"
+#include "audio_bitstream_sm.h"
+
+//TODO: enable sw_decode if required
+#define USE_SWDECODE 0
+
+#if USE_SWDECODE
+#include "SoftMS11.h"
+#endif
#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (32 * 1024)
#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
/* ToDo: Check and update a proper value in msec */
#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
+#define STRING_LENGTH_OF_INTEGER 12
+
+static int send_offload_cmd_l(struct stream_out* out, int command);
+static int get_snd_codec_id(audio_format_t format);
struct pcm_config pcm_config_deep_buffer = {
.channels = 2,
@@ -89,24 +101,1246 @@
.avail_min = 0,
};
-#define STRING_TO_ENUM(string) { #string, string }
+inline int nextMultiple(int n, int m) {
+ return ((n/m) + 1) * m;
+}
-struct string_to_enum {
- const char *name;
- uint32_t value;
-};
+/*******************************************************************************
+Description: check for MS11 supported formats
+*******************************************************************************/
+//TODO: enable sw_decode if required
+#if USE_SWDECODE
+int is_ms11_supported_fromats(int format)
+{
+ ALOGVV("is_ms11_supported_fromats");
+ int main_format = format & AUDIO_FORMAT_MAIN_MASK;
+ if(((main_format == AUDIO_FORMAT_AAC) ||
+ (main_format == AUDIO_FORMAT_HE_AAC_V1) ||
+ (main_format == AUDIO_FORMAT_HE_AAC_V2) ||
+ (main_format == AUDIO_FORMAT_AC3) ||
+ (main_format == AUDIO_FORMAT_AC3_PLUS) ||
+ (main_format == AUDIO_FORMAT_EAC3))) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+#endif
-static const struct string_to_enum out_channels_name_to_enum_table[] = {
- STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
- STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
- STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
-};
+/*******************************************************************************
+Description: check if ac3 can played as pass through without MS11 decoder
+*******************************************************************************/
+//TODO: enable sw_decode if required
+#if USE_SWDECODE
+int can_ac3_passthrough_without_ms11(struct stream_out *out, int format)
+{
+ ALOGVV("can_ac3_passthrough_without_ms11");
+ int main_format = format & AUDIO_FORMAT_MAIN_MASK;
+ if(main_format == AUDIO_FORMAT_AC3) {
+ if(((out->hdmi_format == COMPRESSED) ||
+ (out->hdmi_format == AUTO_DEVICE_FORMAT) ||
+ (out->hdmi_format == COMPRESSED_CONVERT_EAC3_AC3) ||
+ (out->hdmi_format == COMPRESSED_CONVERT_ANY_AC3)) &&
+ ((out->spdif_format == COMPRESSED) ||
+ (out->spdif_format == AUTO_DEVICE_FORMAT) ||
+ (out->spdif_format == COMPRESSED_CONVERT_EAC3_AC3) ||
+ (out->spdif_format == COMPRESSED_CONVERT_ANY_AC3))) {
+ return 1;
+ }
+ }
+ return 0;
+}
+#endif
+
+/*******************************************************************************
+Description: get levels of buffering, interms of number of buffers
+*******************************************************************************/
+int get_buffering_factor(struct stream_out *out)
+{
+ ALOGVV("get_buffering_factor");
+ if((out->format == AUDIO_FORMAT_PCM_16_BIT) ||
+ (out->format == AUDIO_FORMAT_PCM_24_BIT))
+ return 1;
+ else
+ return NUM_OF_PERIODS;
+}
+
+/*******************************************************************************
+Description: get the buffer size based on format and device format type
+*******************************************************************************/
+void get_fragment_size_and_format(struct stream_out *out, int routeFormat, int *fragment_size,
+ int *fragment_count, int *format)
+{
+ ALOGV("get_fragment_size_and_format");
+
+ int frame_size = 0;
+ *format = out->format;
+ *fragment_count = NUM_OF_PERIODS;
+ switch(out->format) {
+ case AUDIO_FORMAT_PCM_16_BIT:
+ frame_size = PCM_16_BITS_PER_SAMPLE * out->channels;
+ /*TODO: do we need below calculation */
+ *fragment_size = nextMultiple(((frame_size * out->sample_rate * TIME_PER_BUFFER)/1000) + MIN_SIZE_FOR_METADATA , frame_size * 32);
+ break;
+ case AUDIO_FORMAT_PCM_24_BIT:
+ frame_size = PCM_24_BITS_PER_SAMPLE * out->channels;
+ *fragment_size = nextMultiple(((frame_size * out->sample_rate * TIME_PER_BUFFER)/1000) + MIN_SIZE_FOR_METADATA, frame_size * 32);
+ break;
+ case AUDIO_FORMAT_AAC:
+ case AUDIO_FORMAT_HE_AAC_V1:
+ case AUDIO_FORMAT_HE_AAC_V2:
+ case AUDIO_FORMAT_AAC_ADIF:
+ case AUDIO_FORMAT_AC3:
+ case AUDIO_FORMAT_AC3_DM:
+ case AUDIO_FORMAT_EAC3:
+ case AUDIO_FORMAT_EAC3_DM:
+ if(routeFormat == ROUTE_UNCOMPRESSED_MCH) {
+ frame_size = PCM_16_BITS_PER_SAMPLE * out->channels;
+ *fragment_size = nextMultiple(AC3_PERIOD_SIZE * out->channels + MIN_SIZE_FOR_METADATA, frame_size * 32);
+ *format = AUDIO_FORMAT_PCM_16_BIT;
+ } else if(routeFormat == ROUTE_UNCOMPRESSED) {
+ frame_size = PCM_16_BITS_PER_SAMPLE * 2;
+ *fragment_size = nextMultiple(AC3_PERIOD_SIZE * 2 + MIN_SIZE_FOR_METADATA, frame_size * 32);
+ *format = AUDIO_FORMAT_PCM_16_BIT;
+ } else {
+ *fragment_size = PERIOD_SIZE_COMPR;
+ }
+ break;
+ case AUDIO_FORMAT_DTS:
+ case AUDIO_FORMAT_DTS_LBR:
+ case AUDIO_FORMAT_MP3:
+ case AUDIO_FORMAT_WMA:
+ case AUDIO_FORMAT_WMA_PRO:
+ case AUDIO_FORMAT_MP2:
+ *fragment_size = PERIOD_SIZE_COMPR;
+ break;
+ default:
+ *fragment_size = PERIOD_SIZE_COMPR;
+ *format = out->format;
+ }
+
+ /*TODO: remove this if fragement count needs to be decided based on the format*/
+ *fragment_count = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
+ fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
+
+ ALOGV("fragment_size: %d, fragment_count: %d", *fragment_size, *fragment_count);
+ return;
+}
+
+/*******************************************************************************
+Description: buffer length updated to player
+*******************************************************************************/
+int get_buffer_length(struct stream_out *out)
+{
+ /* TODO: Do we need below */
+ ALOGV("get_buffer_length");
+ int buffer_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
+ switch(out->format) {
+ case AUDIO_FORMAT_PCM_16_BIT:
+ buffer_size = ((PCM_16_BITS_PER_SAMPLE * out->channels * out->sample_rate * TIME_PER_BUFFER)/1000);
+ break;
+ case AUDIO_FORMAT_PCM_24_BIT:
+ buffer_size = ((PCM_24_BITS_PER_SAMPLE * out->channels * out->sample_rate * TIME_PER_BUFFER)/1000);
+ break;
+ case AUDIO_FORMAT_AAC:
+ case AUDIO_FORMAT_HE_AAC_V1:
+ case AUDIO_FORMAT_HE_AAC_V2:
+ case AUDIO_FORMAT_AAC_ADIF:
+ buffer_size = AAC_BLOCK_PER_CHANNEL_MS11 * out->channels;
+ break;
+ case AUDIO_FORMAT_AC3:
+ case AUDIO_FORMAT_AC3_DM:
+ case AUDIO_FORMAT_EAC3:
+ case AUDIO_FORMAT_EAC3_DM:
+ buffer_size = AC3_BUFFER_SIZE;
+ break;
+ case AUDIO_FORMAT_DTS:
+ case AUDIO_FORMAT_DTS_LBR:
+ case AUDIO_FORMAT_MP3:
+ case AUDIO_FORMAT_WMA:
+ case AUDIO_FORMAT_WMA_PRO:
+ case AUDIO_FORMAT_MP2:
+ buffer_size = COMPR_INPUT_BUFFER_SIZE;
+ break;
+ default:
+ buffer_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
+ }
+
+ /*TODO: remove this if fragement count needs to be decided based on the format*/
+ buffer_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
+ return buffer_size;
+}
+
+/* TODO: Uncomment this when enabling A2DP
+ TODO: add support for the 24 bit playback*/
+#if 0
+/*******************************************************************************
+Description: fix up devices for supporting A2DP playback
+*******************************************************************************/
+void fixUpDevicesForA2DPPlayback(struct stream_out *out)
+{
+ ALOGVV("fixUpDevicesForA2DPPlayback");
+ if(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
+ out->route_audio_to_a2dp = 1;
+ out->devices &= ~AUDIO_DEVICE_OUT_ALL_A2DP;
+ //TODO: add spdif and proxy
+ //out->devices &= ~AUDIO_DEVICE_OUT_SPDIF;
+ //out->devices |= AudioSystem::DEVICE_OUT_PROXY;
+ }
+}
+#endif
+
+/*******************************************************************************
+Description: open temp buffer so that meta data mode can be updated properly
+*******************************************************************************/
+int open_temp_buf_for_metadata(struct stream_out *out)
+{
+ ALOGV("%s", __func__);
+ if (out->write_temp_buf == NULL) {
+ /*Max Period size which is exposed by the compr driver
+ The value needs to be modified when the period size is modified*/
+ out->write_temp_buf = (char *) malloc(PLAYBACK_MAX_PERIOD_SIZE);
+ if (out->write_temp_buf == NULL) {
+ ALOGE("Memory allocation of temp buffer to write pcm to driver failed");
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
+/*******************************************************************************
+Description: get index of handle based on device handle device
+*******************************************************************************/
+struct alsa_handle * get_handle_based_on_devices(struct stream_out *out, int handleDevices)
+{
+ ALOGVV("get_handle_based_on_devices");
+ struct listnode *node;
+ struct alsa_handle *handle = NULL;
+
+ list_for_each(node, &out->session_list) {
+ handle = node_to_item(node, struct alsa_handle, list);
+ if(handle->devices & handleDevices)
+ break;
+ }
+ return handle;
+}
+
+void reset_out_parameters(struct stream_out *out) {
+
+ out->hdmi_format = UNCOMPRESSED;
+ out->spdif_format = UNCOMPRESSED;
+ out->decoder_type = UNCOMPRESSED ;
+ out->dec_conf_set = false;
+ out->min_bytes_req_to_dec = 0;
+ out->is_m11_file_mode = false;
+ out->dec_conf_bufLength = 0;
+ out->first_bitstrm_buf = false;
+ out->open_dec_route = false;
+ out->dec_format_devices = AUDIO_DEVICE_NONE;
+ out->open_dec_mch_route = false;
+ out->dec_mch_format_devices =AUDIO_DEVICE_NONE;
+ out->open_passt_route = false;
+ out->passt_format_devices = AUDIO_DEVICE_NONE;
+ out->sw_open_trans_route = false;
+ out->sw_trans_format_devices = AUDIO_DEVICE_NONE;
+ out->hw_open_trans_route =false ;
+ out->hw_trans_format_devices = AUDIO_DEVICE_NONE;
+ out->channel_status_set = false;
+ out->route_audio_to_a2dp = false;
+ out->is_ms11_file_playback_mode = false;
+ out->write_temp_buf = NULL;
+ return;
+}
+
+struct alsa_handle *get_alsa_handle() {
+
+ struct alsa_handle *handle;
+ handle = (struct alsa_handle *)calloc(1, sizeof(struct alsa_handle));
+ if(handle == NULL) {
+ ALOGE("%s calloc failed for handle", __func__);
+ } else {
+ ALOGE("%s handle is 0x%x", __func__,(uint32_t)handle);
+ }
+
+ return handle;
+}
+
+void free_alsa_handle(struct alsa_handle *handle) {
+
+ if(handle == NULL) {
+ ALOGE("%s Invalid handle", __func__);
+ }
+ free(handle);
+
+ return;
+}
+
+
+struct alsa_handle *get_handle_by_route_format(struct stream_out *out,
+ int route_format)
+{
+ struct listnode *node;
+ struct alsa_handle *handle = NULL;
+ ALOGV("%s",__func__);
+ list_for_each(node, &out->session_list) {
+ handle = node_to_item(node, struct alsa_handle, list);
+ if(handle->route_format & route_format) {
+ ALOGV("%s found handle %x",__func__,(uint32_t)handle);
+ break;
+ }
+ }
+
+ return handle;
+}
+
+/*******************************************************************************
+Description: get the format index
+*******************************************************************************/
+int get_format_index(int format)
+{
+ ALOGVV("get_format_index");
+ int idx = 0,i;
+ for(i=0; i<NUM_SUPPORTED_CODECS; i++) {
+ if(format == format_index[i][0]) {
+ idx = format_index[i][1];
+ break;
+ }
+ }
+ return idx;
+}
+
+int get_compress_available_space(struct alsa_handle *handle)
+{
+ uint32_t ret;
+ size_t avail = 0;
+ struct timespec tstamp;
+ ret = compress_get_hpointer(handle->compr,&avail, &tstamp);
+ if(ret!=0) {
+ ALOGE("cannot get available space\n");
+ } else
+ ret = (int)avail;
+ return ret;
+}
+
+
+/*******************************************************************************
+Description: validate if the decoder requires configuration to be set as first
+ buffer
+*******************************************************************************/
+int is_decoder_config_required(struct stream_out *out)
+{
+ ALOGVV("is_decoder_config_required");
+ int main_format = out->format & AUDIO_FORMAT_MAIN_MASK;
+ uint32_t i;
+ if(!out->is_ms11_file_playback_mode)
+ return 0;
+ for(i=0; i<sizeof(decodersRequireConfig)/sizeof(int); i++)
+ if(main_format == decodersRequireConfig[i])
+ return 1;
+ return 0;
+}
+
+/*******************************************************************************
+Description: query if input buffering mode require
+*******************************************************************************/
+int is_input_buffering_mode_reqd(struct stream_out *out)
+{
+ ALOGVV("is_input_buffering_mode_reqd");
+ if((out->decoder_type == SW_PASSTHROUGH) ||
+ (out->decoder_type == DSP_PASSTHROUGH))
+ return 1;
+ else
+ return 0;
+}
+
+
+
+/*******************************************************************************
+Description: update use case and routing flags
+*******************************************************************************/
+void update_decode_type_and_routing_states(struct stream_out *out)
+{
+ ALOGV("%s", __func__);
+
+ int format_index = get_format_index(out->format);
+ int decodeType, idx;
+
+ out->open_dec_route = false;
+ out->open_dec_mch_route = false;
+ out->open_passt_route = false;
+ out->sw_open_trans_route = false;
+ out->hw_open_trans_route = false;
+ out->dec_format_devices = out->devices;
+ out->dec_mch_format_devices = AUDIO_DEVICE_NONE;
+ out->passt_format_devices = AUDIO_DEVICE_NONE;
+ out->sw_trans_format_devices = AUDIO_DEVICE_NONE;
+ out->hw_trans_format_devices = AUDIO_DEVICE_NONE;
+ out->decoder_type = 0;
+
+//TODO: enable sw_decode if required
+#if USE_SWDECODE
+ if(is_ms11_supported_fromats(out->format))
+ out->use_ms11_decoder = true;
+#endif
+
+ ALOGV("format_index: %d devices %x", format_index,out->devices);
+ if(out->devices & AUDIO_DEVICE_OUT_SPDIF) {
+ decodeType = usecase_docode_hdmi_spdif[NUM_STATES_FOR_EACH_DEVICE_FMT*format_index]
+ [out->spdif_format];
+ ALOGV("SPDIF: decoderType: %d", decodeType);
+ out->decoder_type = decodeType;
+ for(idx=0; idx<NUM_DECODE_PATH; idx++) {
+ if(route_to_driver[idx][DECODER_TYPE_IDX] == decodeType) {
+ switch(route_to_driver[idx][ROUTE_FORMAT_IDX]) {
+ case ROUTE_UNCOMPRESSED:
+ ALOGVV("ROUTE_UNCOMPRESSED");
+ ALOGVV("SPDIF opened with stereo decode");
+ out->open_dec_route = true;
+ break;
+ case ROUTE_UNCOMPRESSED_MCH:
+ ALOGVV("ROUTE_UNCOMPRESSED_MCH");
+ ALOGVV("SPDIF opened with multichannel decode");
+ out->open_dec_mch_route = true;
+ out->dec_format_devices &= ~AUDIO_DEVICE_OUT_SPDIF;
+ out->dec_mch_format_devices |= AUDIO_DEVICE_OUT_SPDIF;
+ break;
+ case ROUTE_COMPRESSED:
+ ALOGVV("ROUTE_COMPRESSED");
+ out->open_passt_route = true;
+ out->dec_format_devices &= ~AUDIO_DEVICE_OUT_SPDIF;
+ out->passt_format_devices = AUDIO_DEVICE_OUT_SPDIF;
+ break;
+ case ROUTE_DSP_TRANSCODED_COMPRESSED:
+ ALOGVV("ROUTE_DSP_TRANSCODED_COMPRESSED");
+ out->hw_open_trans_route = true;
+ out->hw_trans_format_devices = AUDIO_DEVICE_OUT_SPDIF;
+ break;
+ case ROUTE_SW_TRANSCODED_COMPRESSED:
+ ALOGVV("ROUTE_SW_TRANSCODED_COMPRESSED");
+ out->sw_open_trans_route = true;
+ out->dec_format_devices &= ~AUDIO_DEVICE_OUT_SPDIF;
+ out->sw_trans_format_devices = AUDIO_DEVICE_OUT_SPDIF;
+ break;
+ default:
+ ALOGW("INVALID ROUTE for SPDIF, decoderType %d, routeFormat %d",
+ decodeType, route_to_driver[idx][ROUTE_FORMAT_IDX]);
+ break;
+ }
+ }
+ }
+ }
+ if(out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
+ decodeType = usecase_docode_hdmi_spdif[NUM_STATES_FOR_EACH_DEVICE_FMT*format_index]
+ [out->hdmi_format];
+ ALOGV("HDMI: decoderType: %d", decodeType);
+ out->decoder_type |= decodeType;
+ for(idx=0; idx<NUM_DECODE_PATH; idx++) {
+ if(route_to_driver[idx][DECODER_TYPE_IDX] == decodeType) {
+ switch(route_to_driver[idx][ROUTE_FORMAT_IDX]) {
+ case ROUTE_UNCOMPRESSED:
+ ALOGVV("ROUTE_UNCOMPRESSED");
+ ALOGVV("HDMI opened with stereo decode");
+ out->open_dec_route = true;
+ break;
+ case ROUTE_UNCOMPRESSED_MCH:
+ ALOGVV("ROUTE_UNCOMPRESSED_MCH");
+ ALOGVV("HDMI opened with multichannel decode");
+ out->open_dec_mch_route = true;
+ out->dec_format_devices &= ~AUDIO_DEVICE_OUT_AUX_DIGITAL;
+ out->dec_mch_format_devices |= AUDIO_DEVICE_OUT_AUX_DIGITAL;
+ break;
+ case ROUTE_COMPRESSED:
+ ALOGVV("ROUTE_COMPRESSED");
+ out->open_passt_route = true;
+ out->dec_format_devices &= ~AUDIO_DEVICE_OUT_AUX_DIGITAL;
+ out->passt_format_devices |= AUDIO_DEVICE_OUT_AUX_DIGITAL;
+ break;
+ case ROUTE_DSP_TRANSCODED_COMPRESSED:
+ ALOGVV("ROUTE_DSP_TRANSCODED_COMPRESSED");
+ out->hw_open_trans_route = true;
+ out->hw_trans_format_devices |= AUDIO_DEVICE_OUT_AUX_DIGITAL;
+ break;
+ case ROUTE_SW_TRANSCODED_COMPRESSED:
+ ALOGVV("ROUTE_SW_TRANSCODED_COMPRESSED");
+ out->sw_open_trans_route = true;
+ out->dec_format_devices &= ~AUDIO_DEVICE_OUT_AUX_DIGITAL;
+ out->sw_trans_format_devices |= AUDIO_DEVICE_OUT_AUX_DIGITAL;
+ break;
+ default:
+ ALOGW("INVALID ROUTE for HDMI, decoderType %d, routeFormat %d",
+ decodeType, route_to_driver[idx][ROUTE_FORMAT_IDX]);
+ break;
+ }
+ }
+ }
+ }
+ if(out->devices & ~(AUDIO_DEVICE_OUT_AUX_DIGITAL |
+ AUDIO_DEVICE_OUT_SPDIF)) {
+ decodeType = usecase_decode_format[NUM_STATES_FOR_EACH_DEVICE_FMT*format_index];
+ ALOGV("Other Devices: decoderType: %d", decodeType);
+ out->decoder_type |= decodeType;
+ for(idx=0; idx<NUM_DECODE_PATH; idx++) {
+ if(route_to_driver[idx][DECODER_TYPE_IDX] == decodeType) {
+ switch(route_to_driver[idx][ROUTE_FORMAT_IDX]) {
+ case ROUTE_UNCOMPRESSED:
+ ALOGVV("ROUTE_UNCOMPRESSED");
+ ALOGVV("Other Devices opened with stereo decode");
+ out->open_dec_route = true;
+ break;
+ case ROUTE_UNCOMPRESSED_MCH:
+ ALOGVV("ROUTE_UNCOMPRESSED_MCH");
+ ALOGVV("Other Devices opened with multichannel decode");
+ out->open_dec_mch_route = true;
+ out->dec_format_devices &= ~(out->devices &
+ ~(AUDIO_DEVICE_OUT_SPDIF |
+ AUDIO_DEVICE_OUT_AUX_DIGITAL));
+ out->dec_mch_format_devices |= (out->devices &
+ ~(AUDIO_DEVICE_OUT_SPDIF |
+ AUDIO_DEVICE_OUT_AUX_DIGITAL));
+ break;
+ default:
+ ALOGW("INVALID ROUTE for Other Devices, decoderType %d, routeFormat %d",
+ decodeType, route_to_driver[idx][ROUTE_FORMAT_IDX]);
+ break;
+ }
+ }
+ }
+ }
+}
+
+/*******************************************************************************
+Description: update handle states
+*******************************************************************************/
+int update_alsa_handle_state(struct stream_out *out)
+{
+ ALOGV("%s", __func__);
+
+ struct alsa_handle *handle = NULL;
+ struct listnode *node;
+
+ if(out->open_dec_route) {
+ if((handle = get_alsa_handle())== NULL)
+ goto error;
+ list_add_tail(&out->session_list, &handle->list);
+ handle->route_format = ROUTE_UNCOMPRESSED;
+ handle->devices = out->dec_format_devices;
+ handle->usecase = platform_get_usecase(USECASE_AUDIO_PLAYBACK_OFFLOAD);
+ handle->out = out;
+ handle->cmd_pending = false;
+ ALOGD("open_dec_route: routeformat: %d, devices: 0x%x: "
+ ,handle->route_format, handle->devices);
+ }
+ if(out->open_dec_mch_route) {
+ if((handle = get_alsa_handle())== NULL)
+ goto error;
+ list_add_tail(&out->session_list, &handle->list);
+ handle->route_format = ROUTE_UNCOMPRESSED_MCH;
+ handle->devices = out->dec_mch_format_devices;
+ handle->usecase = platform_get_usecase(USECASE_AUDIO_PLAYBACK_OFFLOAD);
+ handle->out = out;
+ handle->cmd_pending = false;
+ ALOGD("OpenMCHDecodeRoute: routeformat: %d, devices: 0x%x: "
+ ,handle->route_format, handle->devices);
+ }
+ if(out->open_passt_route) {
+ if((handle = get_alsa_handle())== NULL)
+ goto error;
+ list_add_tail(&out->session_list, &handle->list);
+ handle->route_format = ROUTE_COMPRESSED;
+ handle->devices = out->passt_format_devices;
+ handle->usecase = platform_get_usecase(USECASE_AUDIO_PLAYBACK_OFFLOAD);
+ handle->out = out;
+ handle->cmd_pending = false;
+ ALOGD("open_passt_route: routeformat: %d, devices: 0x%x: "
+ ,handle->route_format, handle->devices);
+ }
+ if(out->sw_open_trans_route) {
+ if((handle = get_alsa_handle())== NULL)
+ goto error;
+ handle->route_format = ROUTE_SW_TRANSCODED_COMPRESSED;
+ handle->devices = out->sw_trans_format_devices;
+ handle->usecase = platform_get_usecase(USECASE_AUDIO_PLAYBACK_OFFLOAD);
+ handle->out = out;
+ handle->cmd_pending = false;
+ ALOGD("OpenTranscodeRoute: routeformat: %d, devices: 0x%x: "
+ ,handle->route_format, handle->devices);
+ }
+ if(out->hw_open_trans_route) {
+ if((handle = get_alsa_handle())== NULL)
+ goto error;
+ handle->route_format = ROUTE_DSP_TRANSCODED_COMPRESSED;
+ handle->devices = out->hw_trans_format_devices;
+ handle->usecase = platform_get_usecase(USECASE_AUDIO_PLAYBACK_OFFLOAD);
+ handle->out = out;
+ handle->cmd_pending = false;
+ ALOGD("OpenTranscodeRoute: routeformat: %d, devices: 0x%x: "
+ ,handle->route_format, handle->devices);
+ }
+
+return 0;
+
+error:
+ list_for_each(node, &out->session_list) {
+ handle = node_to_item(node, struct alsa_handle, list);
+ free_alsa_handle(handle);
+ }
+
+ return -ENOMEM;
+}
+
+/*******************************************************************************
+Description: setup input path
+*******************************************************************************/
+int allocate_internal_buffers(struct stream_out *out)
+{
+ ALOGV("%s",__func__);
+ int ret = 0;
+ int main_format = out->format & AUDIO_FORMAT_MAIN_MASK;
+
+ /*
+ setup the bitstream state machine
+ */
+ out->bitstrm = ( struct audio_bitstream_sm *)calloc(1,
+ sizeof(struct audio_bitstream_sm));
+ if(!audio_bitstream_init(out->bitstrm, get_buffering_factor(out))) {
+ ALOGE("%s Unable to allocate bitstream buffering for MS11",__func__);
+ free(out->bitstrm);
+ out->bitstrm = NULL;
+ return -EINVAL;
+ }
+
+ if(is_input_buffering_mode_reqd(out))
+ audio_bitstream_start_input_buffering_mode(out->bitstrm);
+
+ /*
+ setup the buffering data required for decode to start
+ AAC_ADIF would require worst case frame size before decode starts
+ other decoder formats handles the partial data, hence threshold is zero.
+ */
+
+ if(main_format == AUDIO_FORMAT_AAC_ADIF)
+ out->min_bytes_req_to_dec = AAC_BLOCK_PER_CHANNEL_MS11*out->channels-1;
+ else
+ out->min_bytes_req_to_dec = 0;
+
+ ret = open_temp_buf_for_metadata(out);
+ if(ret < 0) {
+ free(out->bitstrm);
+ out->bitstrm = NULL;
+ }
+ out->buffer_size = get_buffer_length(out);
+
+ return ret;
+}
+
+/*******************************************************************************
+Description: setup input path
+*******************************************************************************/
+int free_internal_buffers(struct stream_out *out)
+{
+ if(out->bitstrm) {
+ free(out->bitstrm);
+ out->bitstrm = NULL;
+ }
+
+ if(out->write_temp_buf) {
+ free(out->write_temp_buf);
+ out->write_temp_buf = NULL;
+ }
+
+ if(out->dec_conf_buf) {
+ free(out->dec_conf_buf);
+ out->dec_conf_buf = NULL;
+ }
+ return 0;
+}
+
+/*******************************************************************************
+Description: open MS11 instance
+*******************************************************************************/
+//TODO: enable sw_decode if required
+#if USE_SWDECODE
+static int open_ms11_instance(struct stream_out *out)
+{
+ ALOGV("openMS11Instance");
+ int32_t formatMS11;
+ int main_format = out->format & AUDIO_FORMAT_MAIN_MASK;
+ out->ms11_decoder = get_soft_ms11();
+ if(!out->ms11_decoder) {
+ ALOGE("Could not resolve all symbols Required for MS11");
+ return -EINVAL;
+ }
+ /*
+ MS11 created
+ */
+ if(initialize_ms11_function_pointers(out->ms11_decoder) == false) {
+ ALOGE("Could not resolve all symbols Required for MS11");
+ free_soft_ms11(out->ms11_decoder);
+ return -EINVAL;
+ }
+ /*
+ update format
+ */
+ if((main_format == AUDIO_FORMAT_AC3) ||
+ (main_format == AUDIO_FORMAT_EAC3)) {
+ /*TODO: who wil setCOMPRESSED_CONVERT_AC3_ASSOC */
+ if (out->spdif_format == COMPRESSED_CONVERT_AC3_ASSOC)
+ formatMS11 = FORMAT_DOLBY_DIGITAL_PLUS_MAIN_ASSOC;
+ else
+ formatMS11 = FORMAT_DOLBY_DIGITAL_PLUS_MAIN;
+ } else
+ formatMS11 = FORMAT_DOLBY_PULSE_MAIN;
+ /*
+ set the use case to the MS11 decoder and open the stream for decoding
+ */
+ if(ms11_set_usecase_and_open_stream_with_mode(out->ms11_decoder,
+ formatMS11, out->channels, out->sample_rate,
+ out->is_m11_file_mode)) {
+ ALOGE("SetUseCaseAndOpen MS11 failed");
+ free_soft_ms11(out->ms11_decoder);
+ return EINVAL;
+ }
+ if(is_decoder_config_required(out) && out->dec_conf_buf && out->dec_conf_bufLength) {
+ if(ms11_set_aac_config(out->ms11_decoder, (unsigned char *)out->dec_conf_buf,
+ out->dec_conf_bufLength) == true) {
+ out->dec_conf_set = true;
+ }
+ }
+
+ return 0;
+}
+#endif
+/*******************************************************************************
+Description: copy input to internal buffer
+*******************************************************************************/
+void copy_bitstream_internal_buffer(struct audio_bitstream_sm *bitstrm,
+ char *buffer, size_t bytes)
+{
+ // copy bitstream to internal buffer
+ audio_bitstream_copy_to_internal_buffer(bitstrm, (char *)buffer, bytes);
+#ifdef DEBUG
+ dumpInputOutput(INPUT, buffer, bytes, 0);
+#endif
+}
+
+/*******************************************************************************
+Description: set decoder config
+*******************************************************************************/
+//TODO: enable sw_decode if required
+#if USE_SWDECODE
+int setDecodeConfig(struct stream_out *out, char *buffer, size_t bytes)
+{
+ ALOGV("%s ", __func__);
+
+ int main_format = out->format & AUDIO_FORMAT_MAIN_MASK;
+ if(!out->dec_conf_set) {
+ if(main_format == AUDIO_FORMAT_AAC ||
+ main_format == AUDIO_FORMAT_HE_AAC_V1 ||
+ main_format == AUDIO_FORMAT_AAC_ADIF ||
+ main_format == AUDIO_FORMAT_HE_AAC_V2) {
+ if(out->ms11_decoder != NULL) {
+ if(ms11_set_aac_config(out->ms11_decoder,(unsigned char *)buffer,
+ bytes) == false) {
+ ALOGE("AAC decoder config fail");
+ return 0;
+ }
+ }
+ }
+
+ out->dec_conf_bufLength = bytes;
+ if(out->dec_conf_buf)
+ free(out->dec_conf_buf);
+
+ out->dec_conf_buf = malloc(out->dec_conf_bufLength);
+ memcpy(out->dec_conf_buf,
+ buffer,
+ out->dec_conf_bufLength);
+ out->dec_conf_set = true;
+ }
+ out->dec_conf_set = true;
+ return bytes;
+}
+#endif
+
+//TODO: enable sw_decode if required
+#if USE_SWDECODE
+int validate_sw_free_space(struct stream_out* out, int bytes_consumed_in_decode, int *pcm_2ch_len,
+ int *pcm_mch_len, int *passthru_len, int *transcode_len, bool *wait_for_write_done) {
+
+ struct alsa_handle *handle = NULL;
+ char *bufPtr;
+ int copy_output_buffer_size;
+
+ *pcm_2ch_len = *pcm_mch_len = *passthru_len = *transcode_len = *wait_for_write_done = 0;
+
+ if(out->decoder_type & SW_DECODE) {
+ bufPtr = audio_bitstream_get_output_buffer_write_ptr(out->bitstrm,
+ PCM_2CH_OUT);
+ /*TODO: there is chance of illegale access if ms11 output exceeds bitstream
+ output buffer boudary */
+ copy_output_buffer_size = ms11_copy_output_from_ms11buf(out->ms11_decoder,
+ PCM_2CH_OUT,
+ bufPtr);
+ handle = get_handle_by_route_format(out, ROUTE_UNCOMPRESSED);
+ if(handle == NULL) {
+ ALOGE("%s Invalid handle", __func__);
+ return -EINVAL;
+ }
+ if(get_compress_available_space(handle) < copy_output_buffer_size) {
+ handle->cmd_pending = true;
+ *wait_for_write_done = true;
+ }
+ *pcm_2ch_len = copy_output_buffer_size;
+
+ }
+ if(out->decoder_type & SW_DECODE_MCH) {
+ bufPtr=audio_bitstream_get_output_buffer_write_ptr(out->bitstrm,
+ PCM_MCH_OUT);
+ copy_output_buffer_size = ms11_copy_output_from_ms11buf(out->ms11_decoder,
+ PCM_MCH_OUT,
+ bufPtr);
+ handle = get_handle_by_route_format(out, ROUTE_UNCOMPRESSED_MCH);
+ if(handle == NULL) {
+ ALOGE("%s Invalid handle", __func__);
+ return -EINVAL;
+ }
+
+ if(get_compress_available_space(handle) < copy_output_buffer_size) {
+ handle->cmd_pending = true;
+ *wait_for_write_done = true;
+ }
+ *pcm_mch_len = copy_output_buffer_size;
+ }
+ if(out->decoder_type & SW_PASSTHROUGH) {
+ bufPtr = audio_bitstream_get_output_buffer_write_ptr(out->bitstrm, COMPRESSED_OUT);
+ copy_output_buffer_size = bytes_consumed_in_decode;
+ memcpy(bufPtr, audio_bitstream_get_input_buffer_ptr(out->bitstrm), copy_output_buffer_size);
+
+ handle = get_handle_by_route_format(out, ROUTE_COMPRESSED);
+ if(handle == NULL) {
+ ALOGE("%s Invalid handle", __func__);
+ return -EINVAL;
+ }
+
+ if(get_compress_available_space(handle) < copy_output_buffer_size) {
+ handle->cmd_pending = true;
+ *wait_for_write_done = true;
+ }
+ *passthru_len = copy_output_buffer_size;
+ }
+ if(out->decoder_type & SW_TRANSCODE) {
+ bufPtr = audio_bitstream_get_output_buffer_write_ptr(out->bitstrm,
+ TRANSCODE_OUT);
+ copy_output_buffer_size = ms11_copy_output_from_ms11buf(out->bitstrm,
+ COMPRESSED_OUT,
+ bufPtr);
+ handle = get_handle_by_route_format(out, ROUTE_SW_TRANSCODED_COMPRESSED);
+ if(handle == NULL) {
+ ALOGE("%s Invalid handle", __func__);
+ return -EINVAL;
+ }
+ if(get_compress_available_space(handle) < copy_output_buffer_size) {
+ handle->cmd_pending = true;
+ *wait_for_write_done = true;
+ }
+ *transcode_len = copy_output_buffer_size;
+ }
+ return 0;
+}
+#endif
+
+int validate_hw_free_space(struct stream_out *out, int bytes_consumed_in_decode, int *pcm_2ch_len,
+ int *pcm_mch_len, int *passthru_len, int *transcode_len, bool *wait_for_write_done) {
+
+ struct alsa_handle *handle = NULL;
+ char *bufPtr;
+ int copy_output_buffer_size;
+ *pcm_2ch_len = *pcm_mch_len = *passthru_len = *transcode_len = *wait_for_write_done = 0;
+ if(out->decoder_type & DSP_DECODE) {
+ ALOGVV("DSP_DECODE");
+ bufPtr = audio_bitstream_get_output_buffer_write_ptr(out->bitstrm,
+ PCM_MCH_OUT);
+ copy_output_buffer_size = bytes_consumed_in_decode;
+ memcpy(bufPtr, audio_bitstream_get_input_buffer_ptr(out->bitstrm),
+ copy_output_buffer_size);
+ ALOGVV("%s bytes_consumed %d out bufPtr %x, pcm_mch_out_buf_size%d",
+ __func__,bytes_consumed_in_decode,bufPtr,
+ out->bitstrm->pcm_mch_out_buf_size);
+ handle = get_handle_by_route_format(out, ROUTE_UNCOMPRESSED);/*TODO: revisit */
+ if(handle == NULL) {
+ ALOGE("%s Invalid handle", __func__);
+ return -EINVAL;
+ }
+ if(get_compress_available_space(handle) < copy_output_buffer_size) {
+ handle->cmd_pending = true;
+ *wait_for_write_done = true;
+ /*reset input buffer pointer as flinger will resend the data back */
+ audio_bitstream_set_input_buffer_write_ptr(out->bitstrm,
+ -copy_output_buffer_size);
+ *pcm_mch_len = copy_output_buffer_size;
+ }
+ else
+ *pcm_mch_len = copy_output_buffer_size;
+ }
+ if(out->decoder_type & DSP_PASSTHROUGH) {
+ ALOGVV("DSP_PASSTHROUGH");
+ bufPtr = audio_bitstream_get_output_buffer_write_ptr(out->bitstrm, COMPRESSED_OUT);
+ copy_output_buffer_size = bytes_consumed_in_decode;
+ memcpy(bufPtr, audio_bitstream_get_input_buffer_ptr(out->bitstrm), copy_output_buffer_size);
+ handle = get_handle_by_route_format(out, ROUTE_COMPRESSED);
+ if(handle == NULL) {
+ ALOGE("%s Invalid handle", __func__);
+ return -EINVAL;
+ }
+ if(get_compress_available_space(handle) < copy_output_buffer_size) {
+ handle->cmd_pending = true;
+ *wait_for_write_done = true;
+ *passthru_len = copy_output_buffer_size;
+ /*reset input buffer pointer as flinger will resend the data back */
+ audio_bitstream_set_input_buffer_ptr(out->bitstrm, -copy_output_buffer_size);
+ }
+ else
+ *passthru_len = copy_output_buffer_size;
+ }
+ /*TODO: handle DSP Transcode usecase */
+ return 0;
+}
+
+int update_bitstrm_pointers(struct stream_out *out, int pcm_2ch_len,
+ int pcm_mch_len, int passthru_len, int transcode_len) {
+
+ if(out->decoder_type & SW_DECODE) {
+ audio_bitstream_set_output_buffer_write_ptr(out->bitstrm, PCM_2CH_OUT,
+ pcm_2ch_len);
+
+ }
+ if(out->decoder_type & SW_DECODE_MCH || out->decoder_type & DSP_DECODE) {
+ audio_bitstream_set_output_buffer_write_ptr(out->bitstrm, PCM_MCH_OUT, pcm_mch_len);
+ }
+ if(out->decoder_type & SW_PASSTHROUGH || out->decoder_type & DSP_PASSTHROUGH) {
+ audio_bitstream_set_output_buffer_write_ptr(out->bitstrm, COMPRESSED_OUT, passthru_len);
+ }
+ if(out->decoder_type & SW_TRANSCODE) {
+ audio_bitstream_set_output_buffer_write_ptr(out->bitstrm,
+ TRANSCODE_OUT,
+ transcode_len);
+ }
+ return 0;
+}
+
+/*TODO correct it */
+static int configure_compr(struct stream_out *out,
+ struct alsa_handle *handle) {
+ handle->compr_config.codec = (struct snd_codec *)
+ calloc(1, sizeof(struct snd_codec));
+ handle->compr_config.codec->id =
+ get_snd_codec_id(out->format); /*TODO: correct this based on format*/
+ handle->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
+ handle->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
+ handle->compr_config.codec->sample_rate =
+ compress_get_alsa_rate(out->sample_rate);
+ handle->compr_config.codec->bit_rate = out->compr_config.codec->bit_rate;
+ handle->compr_config.codec->ch_in =
+ popcount(out->channel_mask);
+ handle->compr_config.codec->ch_out = handle->compr_config.codec->ch_in;
+ handle->compr_config.codec->format = out->compr_config.codec->format;
+ memcpy(&handle->compr_config.codec->options,
+ &out->compr_config.codec->options,
+ sizeof(union snd_codec_options));
+ return 0;
+}
+
+/*TODO: do we need to apply volume at the session open*/
+static int set_compress_volume(struct alsa_handle *handle, int left, int right)
+{
+
+ struct audio_device *adev = handle->out->dev;
+ struct mixer_ctl *ctl;
+ int volume[2];
+
+ char mixer_ctl_name[44]; // max length of name is 44 as defined
+ char device_id[STRING_LENGTH_OF_INTEGER+1];
+
+ memset(mixer_ctl_name, 0, sizeof(mixer_ctl_name));
+ strlcpy(mixer_ctl_name, "Compress Playback Volume", sizeof(mixer_ctl_name));
+
+ memset(device_id, 0, sizeof(device_id));
+ snprintf(device_id, "%d", handle->device_id, sizeof(device_id));
+
+ strlcat(mixer_ctl_name, device_id, sizeof(mixer_ctl_name));
+
+ ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s",
+ __func__, mixer_ctl_name);
+ return -EINVAL;
+ }
+ volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
+ volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
+ mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
+
+ return 0;
+
+}
+
+/*******************************************************************************
+Description: software decode handling
+*******************************************************************************/
+//TODO: enable sw_decode if required
+#if USE_SWDECODE
+static int sw_decode(struct stream_out *out,
+ char *buffer,
+ size_t bytes,
+ size_t *bytes_consumed,
+ bool *continueDecode)
+{
+ /* bytes pending to be decoded in current buffer*/
+ bool wait_for_write_done = false;
+ int bytes_pending_for_decode = 0;
+ /* bytes consumed in current write buffer */
+ int total_bytes_consumed = 0;
+ size_t copyBytesMS11 = 0;
+ size_t bytes_consumed_in_decode = 0;
+ size_t copy_output_buffer_size = 0;
+ uint32_t outSampleRate = out->sample_rate;
+ uint32_t outChannels = out->channels;
+ char * bufPtr;
+ int pcm_2ch_len, pcm_mch_len, passthru_len, transcode_len;
+ struct alsa_handle *handle = NULL;
+
+ ALOGVV("sw Decode");
+ // eos handling
+ if(bytes == 0) {
+ if(out->format == AUDIO_FORMAT_AAC_ADIF)
+ audio_bitstream_append_silence_internal_buffer(out->bitstrm,
+ out->min_bytes_req_to_dec,0x0);
+ else
+ return false;
+ }
+ /*
+ check for sync word, if present then configure MS11 for fileplayback mode
+ OFF. This is specifically done to handle Widevine usecase, in which the
+ ADTS HEADER is not stripped off by the Widevine parser
+ */
+ if(out->first_bitstrm_buf == true) {
+ uint16_t uData = (*((char *)buffer) << 8) + *((char *)buffer + 1) ;
+ if(ADTS_HEADER_SYNC_RESULT == (uData & ADTS_HEADER_SYNC_MASK)) {
+ ALOGD("Sync word found hence configure MS11 in file_playback Mode OFF");
+ free_soft_ms11(out->ms11_decoder);
+ out->is_m11_file_mode = false;
+ open_ms11_instance(out);
+ }
+ out->first_bitstrm_buf = false;
+ }
+ //decode
+ if(out->decoder_type == SW_PASSTHROUGH) {
+ /*TODO: check if correct */
+ bytes_consumed_in_decode = audio_bitstream_get_size(out->bitstrm);
+ } else {
+ if(audio_bitstream_sufficient_buffer_to_decode(out->bitstrm,
+ out->min_bytes_req_to_dec) == true) {
+ bufPtr = audio_bitstream_get_input_buffer_ptr(out->bitstrm);
+ copyBytesMS11 = audio_bitstream_get_size(out->bitstrm);
+ ms11_copy_bitstream_to_ms11_inpbuf(out->ms11_decoder, bufPtr,copyBytesMS11);
+ bytes_consumed_in_decode = ms11_stream_decode(out->ms11_decoder,
+ &outSampleRate, &outChannels);
+ }
+ }
+
+ if((out->sample_rate != outSampleRate) || (out->channels != outChannels)) {
+ ALOGD("Change in sample rate. New sample rate: %d", outSampleRate);
+ out->sample_rate = outSampleRate;
+ out->channels = outChannels;
+ handle = get_handle_by_route_format(out, ROUTE_UNCOMPRESSED);
+ if(handle !=NULL) {
+ configure_compr(out, handle);
+ handle->compr = compress_open(SOUND_CARD, handle->device_id,
+ COMPRESS_IN, &handle->compr_config);
+ if (handle->compr && !is_compress_ready(handle->compr)) {
+ ALOGE("%s: %s", __func__, compress_get_error(handle->compr));
+ compress_close(handle->compr);
+ handle->compr = NULL;
+ }
+ if (out->offload_callback)
+ compress_nonblock(handle->compr, out->non_blocking);
+
+ set_compress_volume(handle, out->left_volume, out->right_volume);
+ }
+
+ handle = get_handle_by_route_format(out, ROUTE_UNCOMPRESSED_MCH);
+ if(handle !=NULL) {
+ configure_compr(out, handle);
+ handle->compr = compress_open(SOUND_CARD, handle->device_id,
+ COMPRESS_IN, &handle->compr_config);
+ if (handle->compr && !is_compress_ready(handle->compr)) {
+ ALOGE("%s: %s", __func__, compress_get_error(handle->compr));
+ compress_close(handle->compr);
+ handle->compr = NULL;
+ }
+ if (out->offload_callback)
+ compress_nonblock(handle->compr, out->non_blocking);
+ set_compress_volume(handle, out->left_volume, out->right_volume);
+ out->channel_status_set = false;
+ }
+ }
+
+
+ validate_sw_free_space(out, bytes_consumed_in_decode, &pcm_2ch_len, &pcm_mch_len,
+ &passthru_len, &transcode_len, &wait_for_write_done);
+
+ if(wait_for_write_done && out->non_blocking) {
+ send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
+ *continueDecode = false;
+ *bytes_consumed = 0;
+ return 0;
+ } else {
+ update_bitstrm_pointers(out, pcm_2ch_len, pcm_mch_len,
+ passthru_len, transcode_len);
+ audio_bitstream_copy_residue_to_start(out->bitstrm, bytes_consumed_in_decode);
+ *bytes_consumed = bytes_consumed_in_decode;
+ }
+
+ copy_output_buffer_size = pcm_2ch_len + pcm_mch_len + passthru_len + transcode_len;
+ if(copy_output_buffer_size &&
+ audio_bitstream_sufficient_buffer_to_decode(out->bitstrm, out->min_bytes_req_to_dec) == true) {
+ *continueDecode = true;
+ return 0;
+ }
+ return 0;
+}
+#endif
+
+/*******************************************************************************
+Description: dsp decode handling
+*******************************************************************************/
+static bool dsp_decode(struct stream_out *out, char *buffer, size_t bytes,
+ size_t *bytes_consumed, bool *continueDecode)
+{
+ char *bufPtr;
+ size_t bytes_consumed_in_decode = 0;
+
+ bool wait_for_write_done = false;
+ int pcm_2ch_len, pcm_mch_len, passthru_len, transcode_len;
+
+ ALOGVV("dsp_decode");
+ // decode
+ {
+ bytes_consumed_in_decode = audio_bitstream_get_size(out->bitstrm);
+ }
+ // handle change in sample rate
+ {
+ }
+ //TODO: check if the copy of the buffers can be avoided
+ /* can be removed as its not required for dsp decode usecase */
+ *continueDecode = false;
+ validate_hw_free_space(out, bytes_consumed_in_decode, &pcm_2ch_len, &pcm_mch_len,
+ &passthru_len, &transcode_len, &wait_for_write_done);
+
+ if(wait_for_write_done && out->non_blocking) {
+ send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
+ *bytes_consumed = 0;
+ return 0;
+ } else {
+ update_bitstrm_pointers(out, pcm_2ch_len, pcm_mch_len,
+ passthru_len, transcode_len);
+ audio_bitstream_copy_residue_to_start(out->bitstrm, bytes_consumed_in_decode);
+ *bytes_consumed = bytes_consumed_in_decode;
+ ALOGV("%s bytes_consumed_in_decode =%d",__func__,bytes_consumed_in_decode);
+ }
+
+ return 0;
+}
+
+static bool decode(struct stream_out *out, char * buffer, size_t bytes,
+ size_t *bytes_consumed, bool *continuedecode)
+{
+ ALOGV("decode");
+ bool continueDecode = false;
+ int ret = 0;
+
+ // TODO: enable software decode if required
+ /*if (out->use_ms11_decoder) {
+ ret = sw_decode(out, buffer, bytes,
+ bytes_consumed, continuedecode);
+
+ // set channel status
+ // Set the channel status after first frame decode/transcode
+ //TODO: set the SPDIF channel status bits
+ if(out->channel_status_set == false)
+ setSpdifchannel_status(
+ audio_bitstream_get_output_buffer_ptr(out->bitstrm, COMPRESSED_OUT),
+ bytes, AUDIO_PARSER_CODEC_AC3);
+
+ } else */{
+ ret = dsp_decode(out, buffer, bytes,
+ bytes_consumed, continuedecode);
+ // set channel status
+ // Set the channel status after first frame decode/transcode
+ //TODO: set the SPDIF channel status bits
+/* if(out->channel_status_set == false)
+ setSpdifchannel_status(
+ audio_bitstream_get_output_buffer_ptr(out->bitstrm, COMPRESSED_OUT),
+ bytes, AUDIO_PARSER_CODEC_DTS);
+*/
+ }
+ return ret;
+}
+
+/*******************************************************************************
+Description: fixup sample rate and channel info based on format
+*******************************************************************************/
+void fixupSampleRateChannelModeMS11Formats(struct stream_out *out)
+{
+ ALOGV("fixupSampleRateChannelModeMS11Formats");
+ int main_format = out->format & AUDIO_FORMAT_MAIN_MASK;
+ int subFormat = out->format & AUDIO_FORMAT_SUB_MASK;
+/*
+NOTE: For AAC, the output of MS11 is 48000 for the sample rates greater than
+ 24000. The samples rates <= 24000 will be at their native sample rate
+ For AC3, the PCM output is at its native sample rate if the decoding is
+ single decode usecase for MS11.
+*/
+ if(main_format == AUDIO_FORMAT_AAC ||
+ main_format == AUDIO_FORMAT_HE_AAC_V1 ||
+ main_format == AUDIO_FORMAT_HE_AAC_V2 ||
+ main_format == AUDIO_FORMAT_AAC_ADIF) {
+ out->sample_rate = out->sample_rate > 24000 ? 48000 : out->sample_rate;
+ out->channels = 6;
+ } else if (main_format == AUDIO_FORMAT_AC3 ||
+ main_format == AUDIO_FORMAT_EAC3) {
+ /* transcode AC3/EAC3 44.1K to 48K AC3 for non dual-mono clips */
+ if (out->sample_rate == 44100 &&
+ (subFormat != AUDIO_FORMAT_DOLBY_SUB_DM) &&
+ (out->spdif_format == COMPRESSED ||
+ out->spdif_format == AUTO_DEVICE_FORMAT ||
+ out->spdif_format == COMPRESSED_CONVERT_EAC3_AC3) &&
+ (out->hdmi_format == UNCOMPRESSED ||
+ out->hdmi_format == UNCOMPRESSED_MCH)) {
+ out->sample_rate = 48000;
+ out->spdif_format = COMPRESSED_CONVERT_AC3_ASSOC;
+ } else if (out->sample_rate == 44100) {
+ out->spdif_format = UNCOMPRESSED;
+ }
+ out->channels = 6;
+ }
+ ALOGD("ms11 format fixup: out->spdif_format %d, out->hdmi_format %d",
+ out->spdif_format, out->hdmi_format);
+}
static bool is_supported_format(audio_format_t format)
{
- if (format == AUDIO_FORMAT_MP3 ||
- format == AUDIO_FORMAT_AAC)
+ switch (format) {
+ case AUDIO_FORMAT_PCM_16_BIT:
+ case AUDIO_FORMAT_MP3:
+ case AUDIO_FORMAT_AAC:
+ case AUDIO_FORMAT_WMA:
+ case AUDIO_FORMAT_WMA_PRO:
+ case AUDIO_FORMAT_MP2:
return true;
+ default:
+ ALOGE("%s: Unsupported audio format: %x", __func__, format);
+ break;
+ }
return false;
}
@@ -116,14 +1350,26 @@
int id = 0;
switch (format) {
+ case AUDIO_FORMAT_PCM_16_BIT:
+ id = SND_AUDIOCODEC_PCM;
+ break;
case AUDIO_FORMAT_MP3:
id = SND_AUDIOCODEC_MP3;
break;
case AUDIO_FORMAT_AAC:
id = SND_AUDIOCODEC_AAC;
break;
+ case AUDIO_FORMAT_WMA:
+ id = SND_AUDIOCODEC_WMA;
+ break;
+ case AUDIO_FORMAT_WMA_PRO:
+ id = SND_AUDIOCODEC_WMA_PRO;
+ break;
+ case AUDIO_FORMAT_MP2:
+ id = SND_AUDIOCODEC_MP2;
+ break;
default:
- ALOGE("%s: Unsupported audio format", __func__);
+ ALOGE("%s: Unsupported audio format %x", __func__, format);
}
return id;
@@ -173,21 +1419,33 @@
/* must be called iwth out->lock locked */
static void stop_compressed_output_l(struct stream_out *out)
{
+ struct listnode *node;
+ struct alsa_handle *handle;
+ bool is_compr_out = false;
+
+ ALOGV("%s", __func__);
out->offload_state = OFFLOAD_STATE_IDLE;
out->playback_started = 0;
out->send_new_metadata = 1;
- if (out->compr != NULL) {
- compress_stop(out->compr);
- while (out->offload_thread_blocked) {
- pthread_cond_wait(&out->cond, &out->lock);
+ list_for_each(node, &out->session_list) {
+ handle = node_to_item(node, struct alsa_handle, list);
+ if (handle->compr != NULL) {
+ compress_stop(handle->compr);
+ is_compr_out = true;
}
}
+ if (is_compr_out) {
+ while (out->offload_thread_blocked)
+ pthread_cond_wait(&out->cond, &out->lock);
+ }
}
static void *offload_thread_loop(void *context)
{
struct stream_out *out = (struct stream_out *) context;
struct listnode *item;
+ struct listnode *node;
+ struct alsa_handle *handle;
out->offload_state = OFFLOAD_STATE_IDLE;
out->playback_started = 0;
@@ -217,15 +1475,15 @@
cmd = node_to_item(item, struct offload_cmd, node);
list_remove(item);
- ALOGVV("%s STATE %d CMD %d out->compr %p",
- __func__, out->offload_state, cmd->cmd, out->compr);
+ ALOGVV("%s STATE %d CMD %d",
+ __func__, out->offload_state, cmd->cmd);
if (cmd->cmd == OFFLOAD_CMD_EXIT) {
free(cmd);
break;
}
- if (out->compr == NULL) {
+ if (list_empty(&out->session_list)) {
ALOGE("%s: Compress handle is NULL", __func__);
pthread_cond_signal(&out->cond);
continue;
@@ -235,18 +1493,34 @@
send_callback = false;
switch(cmd->cmd) {
case OFFLOAD_CMD_WAIT_FOR_BUFFER:
- compress_wait(out->compr, -1);
+ list_for_each(node, &out->session_list) {
+ handle = node_to_item(node, struct alsa_handle, list);
+ if (handle->compr && handle->cmd_pending) {
+ compress_wait(handle->compr, -1);
+ handle->cmd_pending = false;
+ }
+ }
send_callback = true;
event = STREAM_CBK_EVENT_WRITE_READY;
break;
case OFFLOAD_CMD_PARTIAL_DRAIN:
- compress_next_track(out->compr);
- compress_partial_drain(out->compr);
+ list_for_each(node, &out->session_list) {
+ handle = node_to_item(node, struct alsa_handle, list);
+ if (handle->compr) {
+ compress_next_track(handle->compr);
+ compress_partial_drain(handle->compr);
+ }
+ }
send_callback = true;
event = STREAM_CBK_EVENT_DRAIN_READY;
break;
case OFFLOAD_CMD_DRAIN:
- compress_drain(out->compr);
+ list_for_each(node, &out->session_list) {
+ handle = node_to_item(node, struct alsa_handle, list);
+ if (handle->compr) {
+ compress_drain(handle->compr);
+ }
+ }
send_callback = true;
event = STREAM_CBK_EVENT_DRAIN_READY;
break;
@@ -373,18 +1647,18 @@
return 0;
}
-static int stop_output_stream(struct stream_out *out)
+static int stop_output_stream(struct stream_out *out, struct alsa_handle *handle)
{
int i, ret = 0;
struct audio_usecase *uc_info;
struct audio_device *adev = out->dev;
ALOGV("%s: enter: usecase(%d: %s)", __func__,
- out->usecase, use_case_table[out->usecase]);
- uc_info = get_usecase_from_list(adev, out->usecase);
+ handle->usecase, use_case_table[handle->usecase]);
+ uc_info = get_usecase_from_list(adev, handle->usecase);
if (uc_info == NULL) {
ALOGE("%s: Could not find the usecase (%d) in the list",
- __func__, out->usecase);
+ __func__, handle->usecase);
return -EINVAL;
}
@@ -409,63 +1683,66 @@
return ret;
}
-int start_output_stream(struct stream_out *out)
+int start_output_stream(struct stream_out *out, struct alsa_handle *handle)
{
int ret = 0;
struct audio_usecase *uc_info;
struct audio_device *adev = out->dev;
ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
- __func__, out->usecase, use_case_table[out->usecase], out->devices);
- out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
- if (out->pcm_device_id < 0) {
+ __func__, handle->usecase, use_case_table[handle->usecase], handle->devices);
+ handle->device_id = platform_get_pcm_device_id(handle->usecase, PCM_PLAYBACK);
+ if (handle->device_id < 0) {
ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
- __func__, out->pcm_device_id, out->usecase);
+ __func__, handle->device_id, handle->usecase);
ret = -EINVAL;
goto error_config;
}
uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
- uc_info->id = out->usecase;
+ uc_info->id = handle->usecase;
+ uc_info->handle = handle;
uc_info->type = PCM_PLAYBACK;
uc_info->stream.out = out;
- uc_info->devices = out->devices;
+ uc_info->devices = handle->devices;
uc_info->in_snd_device = SND_DEVICE_NONE;
uc_info->out_snd_device = SND_DEVICE_NONE;
/* This must be called before adding this usecase to the list */
- if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
- check_and_set_hdmi_channels(adev, out->config.channels);
+ //if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
+ // check_and_set_hdmi_channels(adev, out->config.channels);
list_add_tail(&adev->usecase_list, &uc_info->list);
- select_devices(adev, out->usecase);
+ select_devices(adev, handle->usecase);
ALOGV("%s: Opening PCM device card_id(%d) device_id(%d)",
- __func__, 0, out->pcm_device_id);
- if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
- out->pcm = pcm_open(SOUND_CARD, out->pcm_device_id,
- PCM_OUT | PCM_MONOTONIC, &out->config);
- if (out->pcm && !pcm_is_ready(out->pcm)) {
- ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
- pcm_close(out->pcm);
- out->pcm = NULL;
+ __func__, 0, handle->device_id);
+ if (out->uc_strm_type != OFFLOAD_PLAYBACK_STREAM) {
+ handle->compr = NULL;
+ handle->pcm = pcm_open(SOUND_CARD, handle->device_id,
+ PCM_OUT | PCM_MONOTONIC, &handle->config);
+ if (handle->pcm && !pcm_is_ready(handle->pcm)) {
+ ALOGE("%s: %s", __func__, pcm_get_error(handle->pcm));
+ pcm_close(handle->pcm);
+ handle->pcm = NULL;
ret = -EIO;
goto error_open;
}
} else {
- out->pcm = NULL;
- out->compr = compress_open(SOUND_CARD, out->pcm_device_id,
- COMPRESS_IN, &out->compr_config);
- if (out->compr && !is_compress_ready(out->compr)) {
- ALOGE("%s: %s", __func__, compress_get_error(out->compr));
- compress_close(out->compr);
- out->compr = NULL;
+ handle->pcm = NULL;
+ configure_compr(out, handle);
+ handle->compr = compress_open(SOUND_CARD, handle->device_id,
+ COMPRESS_IN, &handle->compr_config);
+ if (handle->compr && !is_compress_ready(handle->compr)) {
+ ALOGE("%s: %s", __func__, compress_get_error(handle->compr));
+ compress_close(handle->compr);
+ handle->compr = NULL;
ret = -EIO;
goto error_open;
}
if (out->offload_callback)
- compress_nonblock(out->compr, out->non_blocking);
+ compress_nonblock(handle->compr, out->non_blocking);
if (adev->visualizer_start_output != NULL)
adev->visualizer_start_output(out->handle);
@@ -473,7 +1750,7 @@
ALOGV("%s: exit", __func__);
return 0;
error_open:
- stop_output_stream(out);
+ stop_output_stream(out, handle);
error_config:
return ret;
}
@@ -494,10 +1771,12 @@
{
struct stream_out *out = (struct stream_out *)stream;
- if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
+ /*if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
return out->compr_config.fragment_size;
+ */
+ return (size_t)out->buffer_size;
- return out->config.period_size * audio_stream_frame_size(stream);
+ //return out->config.period_size * audio_stream_frame_size(stream);
}
static uint32_t out_get_channels(const struct audio_stream *stream)
@@ -523,6 +1802,8 @@
{
struct stream_out *out = (struct stream_out *)stream;
struct audio_device *adev = out->dev;
+ struct listnode *node;
+ struct alsa_handle *handle;
ALOGV("%s: enter: usecase(%d: %s)", __func__,
out->usecase, use_case_table[out->usecase]);
@@ -538,21 +1819,21 @@
pthread_mutex_lock(&adev->lock);
if (!out->standby) {
out->standby = true;
- if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
- if (out->pcm) {
- pcm_close(out->pcm);
- out->pcm = NULL;
+ stop_compressed_output_l(out);
+ out->gapless_mdata.encoder_delay = 0;
+ out->gapless_mdata.encoder_padding = 0;
+
+ list_for_each(node, &out->session_list) {
+ handle = node_to_item(node, struct alsa_handle, list);
+ if (handle->compr != NULL) {
+ compress_close(handle->compr);
+ handle->compr = NULL;
+ } else if (handle->pcm) {
+ pcm_close(handle->pcm);
+ handle->pcm = NULL;
}
- } else {
- stop_compressed_output_l(out);
- out->gapless_mdata.encoder_delay = 0;
- out->gapless_mdata.encoder_padding = 0;
- if (out->compr != NULL) {
- compress_close(out->compr);
- out->compr = NULL;
- }
+ stop_output_stream(out, handle);
}
- stop_output_stream(out);
}
pthread_mutex_unlock(&adev->lock);
pthread_mutex_unlock(&out->lock);
@@ -570,6 +1851,7 @@
int ret = 0;
char value[32];
struct compr_gapless_mdata tmp_mdata;
+ bool gapless_meta_set = true;
if (!out || !parms) {
return -EINVAL;
@@ -579,21 +1861,61 @@
if (ret >= 0) {
tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
} else {
- return -EINVAL;
+ gapless_meta_set = false;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
if (ret >= 0) {
tmp_mdata.encoder_padding = atoi(value);
} else {
- return -EINVAL;
+ gapless_meta_set = false;
}
- out->gapless_mdata = tmp_mdata;
- out->send_new_metadata = 1;
- ALOGV("%s new encoder delay %u and padding %u", __func__,
- out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
+ if (gapless_meta_set) {
+ out->gapless_mdata = tmp_mdata;
+ out->send_new_metadata = 1;
+ ALOGV("%s new encoder delay %u and padding %u", __func__,
+ out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
+ }
+ if(out->format == AUDIO_FORMAT_WMA || out->format == AUDIO_FORMAT_WMA_PRO) {
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_FORMAT_TAG, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->format = atoi(value);
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BLOCK_ALIGN, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.wma.super_block_align = atoi(value);
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BIT_PER_SAMPLE, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.wma.bits_per_sample = atoi(value);
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_CHANNEL_MASK, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.wma.channelmask = atoi(value);
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.wma.encodeopt = atoi(value);
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION1, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.wma.encodeopt1 = atoi(value);
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION2, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.wma.encodeopt2 = atoi(value);
+ }
+ ALOGV("WMA params: fmt %x, balgn %x, sr %d, chmsk %x, encop %x, op1 %x, op2 %x",
+ out->compr_config.codec->format,
+ out->compr_config.codec->options.wma.super_block_align,
+ out->compr_config.codec->options.wma.bits_per_sample,
+ out->compr_config.codec->options.wma.channelmask,
+ out->compr_config.codec->options.wma.encodeopt,
+ out->compr_config.codec->options.wma.encodeopt1,
+ out->compr_config.codec->options.wma.encodeopt2);
+ }
return 0;
}
@@ -608,8 +1930,7 @@
int ret, val = 0;
bool select_new_device = false;
- ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
- __func__, out->usecase, use_case_table[out->usecase], kvpairs);
+ ALOGD("%s: enter: kvpairs: %s", __func__, kvpairs);
parms = str_parms_create_str(kvpairs);
ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
if (ret >= 0) {
@@ -653,13 +1974,64 @@
if (!out->standby)
select_devices(adev, out->usecase);
}
+//TODO:
+//Get the device and device format mapping from the RoutingManager.
+//Decide which streams need to be derouted and which need to opened/closed
+//Update the respective device in each of the handles
+#if 0
+ if (out->uc_strm_type == OFFLOAD_PLAYBACK_STREAM) {
+
+ /* TODO get format form routing manager */
+ update_decode_type_and_routing_states(out);
+
+ if(is_input_buffering_mode_reqd(out))
+ audio_bitstream_start_input_buffering_mode(out->bitstrm);
+ else
+ audio_bitstream_stop_input_buffering_mode(out->bitstrm);
+ /*
+ For the runtime format change, close the device first to avoid any
+ concurrent PCM + Compressed sessions on the same device.
+ */
+ close_handles_for_device_switch(out);
+ if(!out->mopen_dec_route)
+ handleCloseForDeviceSwitch(ROUTE_UNCOMPRESSED);
+
+ if(!out->mopen_dec_mch_route)
+ handleCloseForDeviceSwitch(ROUTE_UNCOMPRESSED_MCH);
+
+ if(!out->mopen_passt_route)
+ handleCloseForDeviceSwitch(ROUTE_COMPRESSED);
+
+ if(!msw_open_trans_route)
+ handleCloseForDeviceSwitch(ROUTE_SW_TRANSCODED_COMPRESSED);
+
+ if(!mhw_open_trans_route)
+ handleCloseForDeviceSwitch(ROUTE_DSP_TRANSCODED_COMPRESSED);
+
+ if(out->mopen_dec_route)
+ handleSwitchAndOpenForDeviceSwitch(mdec_format_devices,
+ ROUTE_UNCOMPRESSED);
+ if(out->mopen_dec_mch_route)
+ handleSwitchAndOpenForDeviceSwitch(mdec_mch_format_devices,
+ ROUTE_UNCOMPRESSED_MCH);
+ if(out->mopen_passt_route)
+ handleSwitchAndOpenForDeviceSwitch(mpasst_format_devices,
+ ROUTE_COMPRESSED);
+ if(out->msw_open_trans_route)
+ handleSwitchAndOpenForDeviceSwitch(msw_trans_format_devices,
+ ROUTE_SW_TRANSCODED_COMPRESSED);
+ if(out->mhw_open_trans_route)
+ handleSwitchAndOpenForDeviceSwitch(mhw_trans_format_devices,
+ ROUTE_DSP_TRANSCODED_COMPRESSED);
+ }
+#endif
pthread_mutex_unlock(&adev->lock);
pthread_mutex_unlock(&out->lock);
}
- if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
- parse_compress_metadata(out, parms);
+ if (out->uc_strm_type == OFFLOAD_PLAYBACK_STREAM) {
+ ret = parse_compress_metadata(out, parms);
}
str_parms_destroy(parms);
@@ -707,42 +2079,206 @@
static uint32_t out_get_latency(const struct audio_stream_out *stream)
{
struct stream_out *out = (struct stream_out *)stream;
+ struct listnode *item;
+ struct alsa_handle *handle;
- if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
+ //TODO: decide based on the clip properties
+ if (out->uc_strm_type == OFFLOAD_PLAYBACK_STREAM)
return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
- return (out->config.period_count * out->config.period_size * 1000) /
- (out->config.rate);
+ item = list_head(&out->session_list);
+ handle = node_to_item(item, struct alsa_handle, list);
+ if(!handle) {
+ ALOGE("%s: error pcm handle NULL", __func__);
+ return -EINVAL;
+ }
+
+ return (handle->config.period_count * handle->config.period_size * 1000) /
+ (handle->config.rate);
}
static int out_set_volume(struct audio_stream_out *stream, float left,
float right)
{
struct stream_out *out = (struct stream_out *)stream;
- int volume[2];
+ struct listnode *node;
+ struct alsa_handle *handle;
+ struct audio_device *adev = out->dev;
+ int ret = -ENOSYS;
+ ALOGV("%s", __func__);
+ pthread_mutex_lock(&out->lock);
+ list_for_each(node, &out->session_list) {
+ handle = node_to_item(node, struct alsa_handle, list);
+ if (handle->pcm && (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH)){
+ /* only take left channel into account: the API is for stereo anyway */
+ out->muted = (left == 0.0f);
+ ret = 0;
+ } else if (handle->compr) {
- if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
- /* only take left channel into account: the API is for stereo anyway */
- out->muted = (left == 0.0f);
- return 0;
- } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
- const char *mixer_ctl_name = "Compress Playback Volume";
- struct audio_device *adev = out->dev;
- struct mixer_ctl *ctl;
+ out->left_volume = left;
+ out->right_volume = right;
- ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
- if (!ctl) {
- ALOGE("%s: Could not get ctl for mixer cmd - %s",
- __func__, mixer_ctl_name);
- return -EINVAL;
+ //ret = set_compress_volume(handle, left, right);
}
- volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
- volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
- mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
- return 0;
+ }
+ pthread_mutex_unlock(&out->lock);
+
+ return ret;
+}
+
+static int write_data(struct stream_out *out, struct alsa_handle *handle,
+ const void *buffer, int bytes) {
+
+ int ret = 0;
+ if (out->uc_strm_type == OFFLOAD_PLAYBACK_STREAM) {
+ ALOGV("%s: writing buffer (%d bytes) to compress device", __func__, bytes);
+
+ ret = compress_write(handle->compr, buffer, bytes);
+ ALOGV("%s: writing buffer (%d bytes) to compress device returned %d",
+ __func__, bytes, ret);
+ /* TODO:disnable this if ms12 */
+
+ if (ret >= 0 && ret < (ssize_t)bytes) {
+ send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
+ }
+ return ret;
+ } else {
+ if (handle->pcm) {
+ if (out->muted)
+ memset((void *)buffer, 0, bytes);
+ ALOGV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
+ ret = pcm_write(handle->pcm, (void *)buffer, bytes);
+ }
}
- return -ENOSYS;
+ if (ret != 0) {
+ if ((handle && handle->pcm))
+ ALOGE("%s: error %d - %s", __func__, ret, pcm_get_error(handle->pcm));
+ out_standby(&out->stream.common);
+ usleep(bytes * 1000000 / audio_stream_frame_size(&out->stream.common) /
+ out_get_sample_rate(&out->stream.common));
+ }
+ return bytes;
+}
+
+/*******************************************************************************
+Description: render
+*******************************************************************************/
+size_t render_offload_data(struct stream_out *out, const void *buffer, size_t bytes)
+{
+ int ret =0;
+ uint32_t renderedPcmBytes = 0;
+ int fragment_size;
+ uint32_t availableSize;
+ int bytes_to_write = bytes;
+ int renderType;
+ /*int metadataLength = sizeof(out->output_meta_data);*/
+ struct listnode *node;
+ struct alsa_handle *handle;
+
+ ALOGV("%s", __func__);
+
+ list_for_each(node, &out->session_list) {
+ handle = node_to_item(node, struct alsa_handle, list);
+ if (out->send_new_metadata) {
+ ALOGVV("send new gapless metadata");
+ compress_set_gapless_metadata(handle->compr, &out->gapless_mdata);
+ }
+
+ switch(handle->route_format) {
+ case ROUTE_UNCOMPRESSED:
+ ALOGVV("ROUTE_UNCOMPRESSED");
+ renderType = PCM_2CH_OUT;
+ break;
+ case ROUTE_UNCOMPRESSED_MCH:
+ ALOGVV("ROUTE_UNCOMPRESSED_MCH");
+ renderType = PCM_MCH_OUT;
+ break;
+ case ROUTE_COMPRESSED:
+ ALOGVV("ROUTE_COMPRESSED");
+ renderType = COMPRESSED_OUT;
+ break;
+ case ROUTE_SW_TRANSCODED_COMPRESSED:
+ ALOGVV("ROUTE_SW_TRANSCODED_COMPRESSED");
+ renderType = TRANSCODE_OUT;
+ break;
+ case ROUTE_DSP_TRANSCODED_COMPRESSED:
+ ALOGVV("ROUTE_DSP_TRANSCODED_COMPRESSED");
+ continue;
+ default:
+ continue;
+ };
+
+ fragment_size = handle->compr_config.fragment_size;
+ /*TODO handle timestamp case */
+#if USE_SWDECODE
+ while(audio_bitstream_sufficient_sample_to_render(out->bitstrm,
+ renderType, 1) == true) {
+ availableSize = audio_bitstream_get_output_buffer_write_ptr(out->bitstrm, renderType) -
+ audio_bitstream_get_output_buffer_ptr(out->bitstrm, renderType);
+ buffer = audio_bitstream_get_output_buffer_ptr(out->bitstrm, renderType);
+ bytes_to_write = availableSize;
+
+ TODO: meta data is only neded for TS mode
+ out->output_meta_data.metadataLength = metadataLength;
+ out->output_meta_data.bufferLength = (availableSize >=
+ (fragment_size - metadataLength)) ?
+ fragment_size - metadataLength :
+ availableSize;
+ bytes_to_write = metadataLength +out->output_meta_data.bufferLength;
+ out->output_meta_data.timestamp = 0;
+ memcpy(out->write_temp_buf, &out->output_meta_data, metadataLength);
+ memcpy(out->write_temp_buf+metadataLength,
+ audio_bitstream_get_output_buffer_ptr(out->bitstrm, renderType),
+ out->output_meta_data.bufferLength);
+ ret = write_data(out, handle, out->write_temp_buf, bytes_to_write);
+#endif
+
+ ret = write_data(out, handle, buffer, bytes_to_write);
+ ALOGD("write_data returned with %d", ret);
+ if(ret < 0) {
+ ALOGE("write_data returned ret < 0");
+ return ret;
+ } else {
+ if (!out->playback_started) {
+ compress_start(handle->compr);
+ }
+ /*TODO:Do we need this
+ if(renderType == ROUTE_UNCOMPRESSED ||
+ (renderType == ROUTE_UNCOMPRESSED_MCH && !out->open_dec_route)) {
+ mFrameCount++;
+ renderedPcmBytes += out->output_meta_data.bufferLength;
+ }*/
+ renderedPcmBytes += ret;
+#if USE_SWDECODE
+ /*iTODO: enable for MS11
+ audio_bitstream_copy_residue_output_start(out->bitstrm, renderType,
+ bytes_to_write);
+ TODO:what if ret<bytes_to_write*/
+#endif
+ }
+#if USE_SWDECODE
+ }
+#endif
+ }
+ out->playback_started = 1;
+ out->offload_state = OFFLOAD_STATE_PLAYING;
+ out->send_new_metadata = 0;
+ return renderedPcmBytes;
+}
+
+size_t render_pcm_data(struct stream_out *out, const void *buffer, size_t bytes)
+{
+ ALOGV("%s", __func__);
+ size_t ret = 0;
+ struct listnode *node;
+ struct alsa_handle *handle;
+ list_for_each(node, &out->session_list) {
+ handle = node_to_item(node, struct alsa_handle, list);
+ ALOGV("%s handle is 0x%x", __func__,(uint32_t)handle);
+ ret = write_data(out, handle, buffer, bytes);
+ }
+ return ret;
}
static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
@@ -751,21 +2287,66 @@
struct stream_out *out = (struct stream_out *)stream;
struct audio_device *adev = out->dev;
ssize_t ret = 0;
+ struct listnode *node;
+ bool continueDecode;
+ struct alsa_handle *handle;
+ size_t bytes_consumed;
+ size_t total_bytes_consumed = 0;
+
+ ALOGV("%s bytes =%d", __func__, bytes);
pthread_mutex_lock(&out->lock);
+
+//TODO: handle a2dp
+/* if (mRouteAudioToA2dp &&
+ mA2dpUseCase == AudioHardwareALSA::USECASE_NONE) {
+ a2dpRenderingControl(A2DP_RENDER_SETUP);
+ }
+*/
+ /* TODO: meta data comes in set_parameter it will be passed in compre_open
+ for all format exxce ms11 format
+ and for ms11 it will be set sdecode fucntion while opneing ms11 instance
+ hence below piece of code is no required*/
+ /*
+ if(!out->dec_conf_set && is_decoder_config_required(out)) {
+ if (setDecodeConfig(out, (char *)buffer, bytes))
+ ALOGD("decoder configuration set");
+ }
+ */
+
if (out->standby) {
out->standby = false;
- pthread_mutex_lock(&adev->lock);
- ret = start_output_stream(out);
- pthread_mutex_unlock(&adev->lock);
- /* ToDo: If use case is compress offload should return 0 */
- if (ret != 0) {
- out->standby = true;
- goto exit;
+ list_for_each(node, &out->session_list) {
+ handle = node_to_item(node, struct alsa_handle, list);
+ pthread_mutex_lock(&adev->lock);
+ ret = start_output_stream(out, handle);
+ pthread_mutex_unlock(&adev->lock);
+ /* ToDo: If use case is compress offload should return 0 */
+ if (ret != 0) {
+ out->standby = true;
+ goto exit;
+ }
}
}
- if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
+ if (out->uc_strm_type == OFFLOAD_PLAYBACK_STREAM) {
+#if USE_SWDECODE
+ //TODO: Enable for MS11
+ copy_bitstream_internal_buffer(out->bitstrm, (char *)buffer, bytes);
+ //DO check if timestamp mode handle partial buffer
+ do {
+
+ bytes_consumed = 0;
+ ret = decode(out, (char *)buffer, bytes, &bytes_consumed, &continueDecode);
+ if(ret < 0)
+ goto exit;
+ /*TODO: check for return size from write when ms11 is removed*/
+ render_offload_data(out, continueDecode);
+ total_bytes_consumed += bytes_consumed;
+
+ } while(continueDecode == true);
+#endif
+#if 0
ALOGVV("%s: writing buffer (%d bytes) to compress device", __func__, bytes);
if (out->send_new_metadata) {
ALOGVV("send new gapless metadata");
@@ -807,11 +2388,50 @@
out_get_sample_rate(&out->stream.common));
}
return bytes;
+#endif
+ ret = render_offload_data(out, buffer, bytes);
+ total_bytes_consumed = ret;
+ } else {
+ ret = render_pcm_data(out, buffer, bytes);
+ total_bytes_consumed = ret;
+ }
+
+exit:
+ pthread_mutex_unlock(&out->lock);
+ ALOGV("total_bytes_consumed %d",total_bytes_consumed);
+ return total_bytes_consumed;
}
static int out_get_render_position(const struct audio_stream_out *stream,
uint32_t *dsp_frames)
{
+ struct listnode *node;
+ struct alsa_handle *handle;
+ struct stream_out *out = (struct stream_out *)stream;
+ struct audio_device *adev = out->dev;
+ *dsp_frames = 0;
+ ALOGV("%s", __func__);
+ pthread_mutex_lock(&out->lock);
+ if ((out->uc_strm_type == OFFLOAD_PLAYBACK_STREAM) && (dsp_frames != NULL)) {
+ list_for_each(node, &out->session_list) {
+ handle = node_to_item(node, struct alsa_handle, list);
+ if ((handle && handle->compr &&
+ handle->route_format != ROUTE_DSP_TRANSCODED_COMPRESSED)){
+ compress_get_tstamp(handle->compr, (unsigned long *)dsp_frames,
+ &out->sample_rate);
+ ALOGV("%s rendered frames %d sample_rate %d",
+ __func__, *dsp_frames, out->sample_rate);
+ }
+ pthread_mutex_unlock(&out->lock);
+ return 0;
+ }
+ }
+ else {
+ pthread_mutex_unlock(&out->lock);
+ return -EINVAL;
+ }
+ return 0;
+#if 0
struct stream_out *out = (struct stream_out *)stream;
*dsp_frames = 0;
if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
@@ -826,6 +2446,7 @@
return 0;
} else
return -EINVAL;
+#endif
}
static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
@@ -847,6 +2468,46 @@
static int out_get_presentation_position(const struct audio_stream_out *stream,
uint64_t *frames, struct timespec *timestamp)
{
+ struct listnode *node;
+ struct alsa_handle *handle;
+ struct stream_out *out = (struct stream_out *)stream;
+ struct audio_device *adev = out->dev;
+ *frames = 0;
+ ALOGV("%s", __func__);
+ pthread_mutex_lock(&out->lock);
+ if ((frames != NULL)) {
+ list_for_each(node, &out->session_list) {
+ handle = node_to_item(node, struct alsa_handle, list);
+ if ((handle && handle->compr &&
+ handle->route_format != ROUTE_DSP_TRANSCODED_COMPRESSED)){
+ compress_get_tstamp(handle->compr, (unsigned long *)frames,
+ &out->sample_rate);
+ clock_gettime(CLOCK_MONOTONIC, timestamp);
+ ALOGV("%s rendered frames %d sample_rate %d",
+ __func__, *frames, out->sample_rate);
+ }
+ else if (handle->pcm) {
+ size_t avail;
+ if (pcm_get_htimestamp(handle->pcm, &avail, timestamp) == 0) {
+ size_t kernel_buffer_size = handle->config.period_size * handle->config.period_count;
+ int64_t signed_frames = out->written - kernel_buffer_size + avail;
+ // This adjustment accounts for buffering after app processor.
+ // It is based on estimated DSP latency per use case, rather than exact.
+ signed_frames -=
+ (platform_render_latency(handle->usecase) * out->sample_rate / 1000000LL);
+
+ // It would be unusual for this value to be negative, but check just in case ...
+ if (signed_frames >= 0) {
+ *frames = signed_frames;
+ }
+ }
+ }
+
+ }
+ }
+ pthread_mutex_unlock(&out->lock);
+ return -EINVAL;
+#if 0
struct stream_out *out = (struct stream_out *)stream;
int ret = -1;
unsigned long dsp_frames;
@@ -887,6 +2548,7 @@
pthread_mutex_unlock(&out->lock);
return ret;
+#endif
}
static int out_set_callback(struct audio_stream_out *stream,
@@ -904,64 +2566,84 @@
static int out_pause(struct audio_stream_out* stream)
{
+ struct listnode *node;
+ struct alsa_handle *handle;
struct stream_out *out = (struct stream_out *)stream;
int status = -ENOSYS;
ALOGV("%s", __func__);
- if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
- pthread_mutex_lock(&out->lock);
- if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
- status = compress_pause(out->compr);
+ pthread_mutex_lock(&out->lock);
+ list_for_each(node, &out->session_list) {
+ handle = node_to_item(node, struct alsa_handle, list);
+ if (handle->compr != NULL && out->offload_state ==
+ OFFLOAD_STATE_PLAYING) {
+ status = compress_pause(handle->compr);
out->offload_state = OFFLOAD_STATE_PAUSED;
}
- pthread_mutex_unlock(&out->lock);
}
+ pthread_mutex_unlock(&out->lock);
return status;
}
static int out_resume(struct audio_stream_out* stream)
{
+ struct listnode *node;
+ struct alsa_handle *handle;
struct stream_out *out = (struct stream_out *)stream;
int status = -ENOSYS;
ALOGV("%s", __func__);
- if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
- status = 0;
- pthread_mutex_lock(&out->lock);
- if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
- status = compress_resume(out->compr);
- out->offload_state = OFFLOAD_STATE_PLAYING;
- }
- pthread_mutex_unlock(&out->lock);
+ pthread_mutex_lock(&out->lock);
+ list_for_each(node, &out->session_list) {
+ handle = node_to_item(node, struct alsa_handle, list);
+ status = 0;
+ if (handle->compr != NULL && out->offload_state ==
+ OFFLOAD_STATE_PAUSED) {
+ status = compress_resume(handle->compr);
+ out->offload_state = OFFLOAD_STATE_PLAYING;
+ }
}
+ pthread_mutex_unlock(&out->lock);
return status;
}
static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
{
+ struct listnode *node;
+ struct alsa_handle *handle;
struct stream_out *out = (struct stream_out *)stream;
int status = -ENOSYS;
ALOGV("%s", __func__);
- if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
- pthread_mutex_lock(&out->lock);
- if (type == AUDIO_DRAIN_EARLY_NOTIFY)
- status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
- else
- status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
- pthread_mutex_unlock(&out->lock);
+ pthread_mutex_lock(&out->lock);
+ list_for_each(node, &out->session_list) {
+ handle = node_to_item(node, struct alsa_handle, list);
+ status = 0;
+ if (handle->compr != NULL) {
+ if (type == AUDIO_DRAIN_EARLY_NOTIFY)
+ status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
+ else
+ status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
+ }
}
+ pthread_mutex_unlock(&out->lock);
return status;
}
static int out_flush(struct audio_stream_out* stream)
{
+ struct listnode *node;
+ struct alsa_handle *handle;
struct stream_out *out = (struct stream_out *)stream;
+ int status = -ENOSYS;
ALOGV("%s", __func__);
- if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
- pthread_mutex_lock(&out->lock);
- stop_compressed_output_l(out);
- pthread_mutex_unlock(&out->lock);
- return 0;
+ pthread_mutex_lock(&out->lock);
+ list_for_each(node, &out->session_list) {
+ handle = node_to_item(node, struct alsa_handle, list);
+ status = 0;
+ if (handle->compr != NULL) {
+ stop_compressed_output_l(out);
+ }
}
- return -ENOSYS;
+ pthread_mutex_unlock(&out->lock);
+ return status;
}
int adev_open_output_stream(struct audio_hw_device *dev,
@@ -973,7 +2655,9 @@
{
struct audio_device *adev = (struct audio_device *)dev;
struct stream_out *out;
- int i, ret;
+ struct alsa_handle *device_handle = NULL;
+ int i, ret, channels;
+ struct listnode *item;
ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
__func__, config->sample_rate, config->channel_mask, devices, flags);
@@ -982,7 +2666,9 @@
if (devices == AUDIO_DEVICE_NONE)
devices = AUDIO_DEVICE_OUT_SPEAKER;
+ list_init(&out->session_list);
+ reset_out_parameters(out);
out->flags = flags;
out->devices = devices;
out->dev = adev;
@@ -990,109 +2676,13 @@
out->sample_rate = config->sample_rate;
out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
+ out->config = config;
out->handle = handle;
+//*TODO: get hdmi/spdif format/channels from routing manager and intialize out->spdif_format & out->hdmi_format*/
/* Init use case and pcm_config */
- if (out->flags == AUDIO_OUTPUT_FLAG_DIRECT &&
- out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
- pthread_mutex_lock(&adev->lock);
- ret = read_hdmi_channel_masks(out);
- pthread_mutex_unlock(&adev->lock);
- if (ret != 0)
- goto error_open;
-
- if (config->sample_rate == 0)
- config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
- if (config->channel_mask == 0)
- config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
-
- out->channel_mask = config->channel_mask;
- out->sample_rate = config->sample_rate;
- out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
- out->config = pcm_config_hdmi_multi;
- out->config.rate = config->sample_rate;
- out->config.channels = popcount(out->channel_mask);
- out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
- } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
- if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
- config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
- ALOGE("%s: Unsupported Offload information", __func__);
- ret = -EINVAL;
- goto error_open;
- }
- if (!is_supported_format(config->offload_info.format)) {
- ALOGE("%s: Unsupported audio format", __func__);
- ret = -EINVAL;
- goto error_open;
- }
-
- out->compr_config.codec = (struct snd_codec *)
- calloc(1, sizeof(struct snd_codec));
-
- out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
- if (config->offload_info.channel_mask)
- out->channel_mask = config->offload_info.channel_mask;
- else if (config->channel_mask)
- out->channel_mask = config->channel_mask;
- out->format = config->offload_info.format;
- out->sample_rate = config->offload_info.sample_rate;
-
- out->stream.set_callback = out_set_callback;
- out->stream.pause = out_pause;
- out->stream.resume = out_resume;
- out->stream.drain = out_drain;
- out->stream.flush = out_flush;
-
- out->compr_config.codec->id =
- get_snd_codec_id(config->offload_info.format);
- out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
- out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
- out->compr_config.codec->sample_rate =
- compress_get_alsa_rate(config->offload_info.sample_rate);
- out->compr_config.codec->bit_rate =
- config->offload_info.bit_rate;
- out->compr_config.codec->ch_in =
- popcount(config->channel_mask);
- out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
-
- if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
- out->non_blocking = 1;
-
- out->send_new_metadata = 1;
- create_offload_callback_thread(out);
- ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
- __func__, config->offload_info.version,
- config->offload_info.bit_rate);
- } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
- out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
- out->config = pcm_config_low_latency;
- out->sample_rate = out->config.rate;
- } else {
- out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
- out->config = pcm_config_deep_buffer;
- out->sample_rate = out->config.rate;
- }
-
- if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
- if(adev->primary_output == NULL)
- adev->primary_output = out;
- else {
- ALOGE("%s: Primary output is already opened", __func__);
- ret = -EEXIST;
- goto error_open;
- }
- }
-
- /* Check if this usecase is already existing */
- pthread_mutex_lock(&adev->lock);
- if (get_usecase_from_list(adev, out->usecase) != NULL) {
- ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
- pthread_mutex_unlock(&adev->lock);
- ret = -EEXIST;
- goto error_open;
- }
- pthread_mutex_unlock(&adev->lock);
-
+ out->hdmi_format = UNCOMPRESSED;
+ out->spdif_format = UNCOMPRESSED;
out->stream.common.get_sample_rate = out_get_sample_rate;
out->stream.common.set_sample_rate = out_set_sample_rate;
out->stream.common.get_buffer_size = out_get_buffer_size;
@@ -1119,6 +2709,138 @@
pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
+ if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
+ ALOGE("%s: Usecase is OFFLOAD", __func__);
+ if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
+ config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
+ ALOGE("%s: Unsupported Offload information", __func__);
+ ret = -EINVAL;
+ goto error_open;
+ }
+
+ if (!is_supported_format(config->offload_info.format)) {
+ ALOGE("%s: Unsupported audio format", __func__);
+ ret = -EINVAL;
+ goto error_open;
+ }
+ out->compr_config.codec = (struct snd_codec *)
+ calloc(1, sizeof(struct snd_codec));
+ //Session/clip config.
+ out->format = config->offload_info.format;
+ out->sample_rate = config->offload_info.sample_rate;
+ out->compr_config.codec->id =
+ get_snd_codec_id(config->offload_info.format);
+ out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
+ out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
+ out->compr_config.codec->sample_rate =
+ compress_get_alsa_rate(config->offload_info.sample_rate);
+ out->compr_config.codec->bit_rate =
+ config->offload_info.bit_rate;
+ out->compr_config.codec->ch_in =
+ popcount(config->channel_mask);
+ out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
+
+ if (config->offload_info.channel_mask)
+ out->channel_mask = config->offload_info.channel_mask;
+ else if (config->channel_mask)
+ out->channel_mask = config->channel_mask;
+ out->uc_strm_type = OFFLOAD_PLAYBACK_STREAM;
+
+ //Initialize the handles
+ /* ------------------------------------------------------------------------
+ Update use decoder type and routing flags and corresponding states
+ decoderType will cache the decode types such as decode/passthrough/transcode
+ and in s/w or dsp. Besides, the states to open decode/passthrough/transcode
+ handles with the corresponding devices and device formats are updated
+ -------------------------------------------------------------------------*/
+ update_decode_type_and_routing_states(out);
+
+ /* ------------------------------------------------------------------------
+ Update rxHandle states
+ Based on the states, we open the driver and store the handle at appropriate
+ index
+ -------------------------------------------------------------------------*/
+ update_alsa_handle_state(out);
+
+ /* ------------------------------------------------------------------------
+ setup routing
+ -------------------------------------------------------------------------*/
+ ret = allocate_internal_buffers(out);
+ if(ret < 0) {
+ ALOGE("%s:Error %d",__func__, ret);
+ goto error_handle;
+ }
+
+ //Callbacks
+ out->stream.set_callback = out_set_callback;
+ out->stream.pause = out_pause;
+ out->stream.resume = out_resume;
+ out->stream.drain = out_drain;
+ out->stream.flush = out_flush;
+
+ if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
+ out->non_blocking = 1;
+
+ out->send_new_metadata = 1;
+ create_offload_callback_thread(out);
+ ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
+ __func__, config->offload_info.version,
+ config->offload_info.bit_rate);
+ } else { //if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
+ ALOGE("%s: Usecase is DEEP_BUFFER", __func__);
+ if((device_handle = get_alsa_handle())== NULL)
+ goto error_handle;
+ list_add_tail(&out->session_list, &device_handle->list);
+ device_handle->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
+ device_handle->config = pcm_config_deep_buffer;
+ device_handle->out = out;
+ device_handle->cmd_pending = false;
+ out->sample_rate = device_handle->config.rate;
+ out->uc_strm_type = DEEP_BUFFER_PLAYBACK_STREAM;
+ out->buffer_size = device_handle->config.period_size *
+ audio_stream_frame_size(&out->stream.common);
+ }/* else {
+ if((device_handle = get_alsa_handle())== NULL)
+ goto error_handle;
+ list_add_tail(&out->session_list, &device_handle->list);
+ device_handle->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
+ device_handle->config = pcm_config_low_latency;
+ device_handle->sample_rate = device_handle->config.rate;
+ device_handle->out = out;
+ device_handle->cmd_pending = false;
+ out->uc_strm_type = LOW_LATENCY_PLAYBACK_STREAM;
+ out->buffer_size = device_handle->config.period_size *
+ audio_stream_frame_size(&out->stream.common);
+ }*/
+
+ if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
+ ALOGE("%s: Usecase is primary ", __func__);
+ if(adev->primary_output == NULL)
+ adev->primary_output = out;
+ else {
+ ALOGE("%s: Primary output is already opened", __func__);
+ ret = -EEXIST;
+ goto error_open;
+ }
+ }
+
+ /* Check if this usecase is already existing */
+ pthread_mutex_lock(&adev->lock);
+ if (out->uc_strm_type != OFFLOAD_PLAYBACK_STREAM) {
+ if (get_usecase_from_list(adev, device_handle->usecase) != NULL) {
+ ALOGE("%s: Usecase (%d) is already present", __func__,
+ device_handle->usecase);
+ pthread_mutex_unlock(&adev->lock);
+ ret = -EEXIST;
+ goto error_open;
+ }
+ }
+ pthread_mutex_unlock(&adev->lock);
+
+
+ /* out->muted = false; by calloc() */
+
+
config->format = out->stream.common.get_format(&out->stream.common);
config->channel_mask = out->stream.common.get_channels(&out->stream.common);
config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
@@ -1127,6 +2849,17 @@
ALOGV("%s: exit", __func__);
return 0;
+error_handle:
+ ret = -EINVAL;
+ ALOGE("%s: exit: error handle %d", __func__, ret);
+ while (!list_empty(&out->session_list)) {
+ item = list_head(&out->session_list);
+ list_remove(item);
+ device_handle = node_to_item(item, struct alsa_handle, list);
+ platform_free_usecase(device_handle->usecase);
+ free_alsa_handle(device_handle);
+ }
+
error_open:
free(out);
*stream_out = NULL;
@@ -1139,17 +2872,28 @@
{
struct stream_out *out = (struct stream_out *)stream;
struct audio_device *adev = out->dev;
- int ret = 0;
+ struct listnode *item;
+ struct alsa_handle *handle;
- ALOGV("%s: enter", __func__);
+ ALOGV("%s", __func__);
+
out_standby(&stream->common);
-
- if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
+ if (out->uc_strm_type == OFFLOAD_PLAYBACK_STREAM) {
destroy_offload_callback_thread(out);
- if (out->compr_config.codec != NULL)
- free(out->compr_config.codec);
+ while (!list_empty(&out->session_list)) {
+ item = list_head(&out->session_list);
+ list_remove(item);
+ handle = node_to_item(item, struct alsa_handle, list);
+ if(handle->compr_config.codec != NULL)
+ free(handle->compr_config.codec);
+ platform_free_usecase(handle->usecase);
+ free_alsa_handle(handle);
+ }
+ free(out->compr_config.codec);
}
+
+ free_internal_buffers(out);
pthread_cond_destroy(&out->cond);
pthread_mutex_destroy(&out->lock);
free(stream);
diff --git a/hal_mpq/mpq8092/platform.c b/hal_mpq/mpq8092/platform.c
index d7d67d5..3c1b4f7 100644
--- a/hal_mpq/mpq8092/platform.c
+++ b/hal_mpq/mpq8092/platform.c
@@ -91,20 +91,39 @@
struct csd_data *csd;
};
-static const int pcm_device_table[AUDIO_USECASE_MAX][2] = {
- [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {DEEP_BUFFER_PCM_DEVICE,
- DEEP_BUFFER_PCM_DEVICE},
- [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
- LOWLATENCY_PCM_DEVICE},
- [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {MULTIMEDIA2_PCM_DEVICE,
- MULTIMEDIA2_PCM_DEVICE},
+static int pcm_device_table[AUDIO_USECASE_MAX][4] = {
+ [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
+ DEEP_BUFFER_PCM_DEVICE,
+ DEEP_BUFFER_PCM_DEVICE, 0},
+ [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
+ LOWLATENCY_PCM_DEVICE,
+ LOWLATENCY_PCM_DEVICE, 0},
+ [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {USECASE_AUDIO_PLAYBACK_MULTI_CH,
+ MULTIMEDIA2_PCM_DEVICE,
+ MULTIMEDIA2_PCM_DEVICE, 0},
+ [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {USECASE_AUDIO_PLAYBACK_MULTI_CH,
+ MULTI_CHANNEL_PCM_DEVICE,
+ MULTI_CHANNEL_PCM_DEVICE, 0},
[USECASE_AUDIO_PLAYBACK_OFFLOAD] =
- {PLAYBACK_OFFLOAD_DEVICE, PLAYBACK_OFFLOAD_DEVICE},
- [USECASE_AUDIO_RECORD] = {AUDIO_RECORD_PCM_DEVICE, AUDIO_RECORD_PCM_DEVICE},
- [USECASE_AUDIO_RECORD_COMPRESS] = {COMPRESS_CAPTURE_DEVICE, COMPRESS_CAPTURE_DEVICE},
- [USECASE_AUDIO_RECORD_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
- LOWLATENCY_PCM_DEVICE},
- [USECASE_AUDIO_RECORD_FM_VIRTUAL] = {MULTIMEDIA2_PCM_DEVICE,
+ {USECASE_AUDIO_PLAYBACK_OFFLOAD, PLAYBACK_OFFLOAD_DEVICE1,
+ PLAYBACK_OFFLOAD_DEVICE1, 0},
+ [USECASE_AUDIO_PLAYBACK_OFFLOAD1] = {USECASE_AUDIO_PLAYBACK_OFFLOAD,
+ PLAYBACK_OFFLOAD_DEVICE2,
+ PLAYBACK_OFFLOAD_DEVICE2, 0},
+ [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = {USECASE_AUDIO_PLAYBACK_OFFLOAD,
+ PLAYBACK_OFFLOAD_DEVICE3,
+ PLAYBACK_OFFLOAD_DEVICE3, 0},
+ [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = {USECASE_AUDIO_PLAYBACK_OFFLOAD,
+ PLAYBACK_OFFLOAD_DEVICE4,
+ PLAYBACK_OFFLOAD_DEVICE4, 0},
+ [USECASE_AUDIO_RECORD] = {USECASE_AUDIO_RECORD, AUDIO_RECORD_PCM_DEVICE,
+ AUDIO_RECORD_PCM_DEVICE, 0},
+ [USECASE_AUDIO_RECORD_COMPRESS] = {USECASE_AUDIO_RECORD_COMPRESS, COMPRESS_CAPTURE_DEVICE,
+ COMPRESS_CAPTURE_DEVICE, 0},
+ [USECASE_AUDIO_RECORD_LOW_LATENCY] = {USECASE_AUDIO_RECORD_LOW_LATENCY,
+ LOWLATENCY_PCM_DEVICE,
+ LOWLATENCY_PCM_DEVICE, 0},
+ /* [USECASE_AUDIO_RECORD_FM_VIRTUAL] = {,
MULTIMEDIA2_PCM_DEVICE},
[USECASE_AUDIO_PLAYBACK_FM] = {FM_PLAYBACK_PCM_DEVICE, FM_CAPTURE_PCM_DEVICE},
[USECASE_VOICE_CALL] = {VOICE_CALL_PCM_DEVICE, VOICE_CALL_PCM_DEVICE},
@@ -124,6 +143,7 @@
INCALL_MUSIC_UPLINK2_PCM_DEVICE},
[USECASE_AUDIO_SPKR_CALIB_RX] = {SPKR_PROT_CALIB_RX_PCM_DEVICE, -1},
[USECASE_AUDIO_SPKR_CALIB_TX] = {-1, SPKR_PROT_CALIB_TX_PCM_DEVICE},
+*/
};
/* Array to store sound devices */
@@ -593,12 +613,39 @@
{
int device_id;
if (device_type == PCM_PLAYBACK)
- device_id = pcm_device_table[usecase][0];
- else
device_id = pcm_device_table[usecase][1];
+ else
+ device_id = pcm_device_table[usecase][2];
return device_id;
}
+audio_usecase_t platform_get_usecase(
+ audio_usecase_stream_type_t uc_type)
+{
+ int i = 0;
+ for(i =0;i<AUDIO_USECASE_MAX; i++)
+ if((pcm_device_table[i][0] == (int)uc_type) &&
+ (pcm_device_table[i][3] == 0)) {
+ pcm_device_table[i][3] = 1;
+ break;
+ }
+
+ if(i == AUDIO_USECASE_MAX)
+ return -EINVAL;
+ else
+ return (audio_usecase_t)i;
+}
+
+int platform_free_usecase(audio_usecase_t uc_id)
+{
+ if(uc_id >= AUDIO_USECASE_MAX) {
+ ALOGV("%s: enter: invalid usecase(%d)", __func__, uc_id);
+ return -EINVAL;
+ }
+ pcm_device_table[uc_id][3] = 0;
+ return 0;
+}
+
int platform_send_audio_calibration(void *platform, snd_device_t snd_device)
{
struct platform_data *my_data = (struct platform_data *)platform;
diff --git a/hal_mpq/mpq8092/platform.h b/hal_mpq/mpq8092/platform.h
index 7559258..2a81df5 100644
--- a/hal_mpq/mpq8092/platform.h
+++ b/hal_mpq/mpq8092/platform.h
@@ -26,6 +26,7 @@
FLUENCE_QUAD_MIC = 0x2,
};
+#include <hardware/audio.h>
/*
* Below are the devices for which is back end is same, SLIMBUS_0_RX.
* All these devices are handled by the internal HW codec. We can
@@ -34,6 +35,8 @@
#define AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND \
(AUDIO_DEVICE_OUT_EARPIECE | AUDIO_DEVICE_OUT_SPEAKER | \
AUDIO_DEVICE_OUT_WIRED_HEADSET | AUDIO_DEVICE_OUT_WIRED_HEADPHONE)
+/*TODO remove this once define in audio.h */
+#define AUDIO_DEVICE_OUT_SPDIF 0x4000
/* Sound devices specific to the platform
* The DEVICE_OUT_* and DEVICE_IN_* should be mapped to these sound
@@ -154,6 +157,16 @@
#define LOW_LATENCY_OUTPUT_PERIOD_SIZE 240
#define LOW_LATENCY_OUTPUT_PERIOD_COUNT 2
+/*******************************************************************************
+ADTS HEADER PARSING
+*******************************************************************************/
+//Required for ADTS Header Parsing
+#define ADTS_HEADER_SYNC_RESULT 0xfff0
+#define ADTS_HEADER_SYNC_MASK 0xfff6
+/*******************************************************************************
+HDMI and SPDIF Device Output format control
+*******************************************************************************/
+
#define HDMI_MULTI_PERIOD_SIZE 336
#define HDMI_MULTI_PERIOD_COUNT 8
#define HDMI_MULTI_DEFAULT_CHANNEL_COUNT 6
@@ -174,8 +187,14 @@
#define INCALL_MUSIC_UPLINK2_PCM_DEVICE 16
#define SPKR_PROT_CALIB_RX_PCM_DEVICE 5
#define SPKR_PROT_CALIB_TX_PCM_DEVICE 22
-#define PLAYBACK_OFFLOAD_DEVICE 9
#define COMPRESS_VOIP_CALL_PCM_DEVICE 3
+#define MULTI_CHANNEL_PCM_DEVICE 1
+#define VOICE_CALL_PCM_DEVICE 2
+//TODO: update the device number as per the dai links
+#define PLAYBACK_OFFLOAD_DEVICE1 2
+#define PLAYBACK_OFFLOAD_DEVICE2 3
+#define PLAYBACK_OFFLOAD_DEVICE3 4
+#define PLAYBACK_OFFLOAD_DEVICE4 19
#define LOWLATENCY_PCM_DEVICE 15
#define COMPRESS_CAPTURE_DEVICE 19
@@ -235,11 +254,48 @@
void hw_info_append_hw_type(void *hw_info, snd_device_t snd_device,
char *device_name);
-#define SAMPLES_PER_CHANNEL 1536*2
+/*******************************************************************************
+USECASES AND THE CORRESPONDING DEVICE FORMATS THAT WE SUPPORT IN HAL
+*******************************************************************************/
+/*
+In general max of 2 for pass through. Additional 1 for handling transcode
+as the existence of transcode is with a PCM handle followed by transcode handle
+So, a (AC3/EAC3) pass through + trancode require - 1 for pas through, 1 - pcm and
+1 - transcode
+*/
+#define NUM_DEVICES_SUPPORT_COMPR_DATA 2+1
+#define NUM_SUPPORTED_CODECS 16
+#define NUM_COLUMN_FOR_INDEXING 2
+#define NUM_STATES_FOR_EACH_DEVICE_FMT 3
+#define DECODER_TYPE_IDX 0
+#define ROUTE_FORMAT_IDX 1
+
+#define MIN_SIZE_FOR_METADATA 64
+#define NUM_OF_PERIODS 8
+/*Period size to be a multiple of chanels * bitwidth,
+So min period size = LCM (1,2...8) * 4*/
+#define PERIOD_SIZE_COMPR 3360
+#define MS11_INPUT_BUFFER_SIZE 1536
+/*Max Period size which is exposed by the compr driver
+The value needs to be modified when the period size is modified*/
+#define PLAYBACK_MAX_PERIOD_SIZE (160 * 1024)
+
+#define COMPR_INPUT_BUFFER_SIZE (PERIOD_SIZE_COMPR - MIN_SIZE_FOR_METADATA)
+#define PCM_16_BITS_PER_SAMPLE 2
+#define PCM_24_BITS_PER_SAMPLE 3
+#define AC3_PERIOD_SIZE 1536 * PCM_16_BITS_PER_SAMPLE
+#define TIME_PER_BUFFER 40 //Time duration in ms
+#define SAMPLES_PER_CHANNEL 32*1024 //1536*2 /*TODO:correct it
#define MAX_INPUT_CHANNELS_SUPPORTED 8
#define FACTOR_FOR_BUFFERING 2
#define STEREO_CHANNELS 2
#define MAX_OUTPUT_CHANNELS_SUPPORTED 8
+#define PCM_BLOCK_PER_CHANNEL_MS11 1536*2
+#define AAC_BLOCK_PER_CHANNEL_MS11 768
+#define NUMBER_BITS_IN_A_BYTE 8
+#define AC3_BUFFER_SIZE 1920*2
+
+#define MAX_OUTPUT_CHANNELS_SUPPORTED 8
#define PCM_2CH_OUT 0
#define PCM_MCH_OUT 1
@@ -248,6 +304,333 @@
#define TRANSCODE_OUT 3
#define FACTOR_FOR_BUFFERING 2
+#define NUM_DEVICES_SUPPORT_COMPR_DATA 2+1
+#define NUM_SUPPORTED_CODECS 16
+#define NUM_COLUMN_FOR_INDEXING 2
+#define NUM_STATES_FOR_EACH_DEVICE_FMT 3
+#define DECODER_TYPE_IDX 0
+#define ROUTE_FORMAT_IDX 1
+#define NUM_OF_PERIODS 8
+
+enum {
+ LPCM,
+ MULTI_CH_PCM,
+ COMPR,
+ TRANSCODE
+};
+
+
+/*
+List of indexes of the supported formats
+Redundant formats such as (AAC-LC, HEAAC) are removed from the indexes as they
+are treated with the AAC format
+*/
+enum {
+ PCM_IDX = 0,
+ AAC_IDX,
+ AC3_IDX,
+ EAC3_IDX,
+ DTS_IDX,
+ DTS_LBR_IDX,
+ MP3_IDX,
+ WMA_IDX,
+ WMA_PRO_IDX,
+ MP2_IDX,
+ ALL_FORMATS_IDX
+};
+/*
+List of pass through's supported in the current usecases
+*/
+enum {
+ NO_PASSTHROUGH = 0,
+ AC3_PASSTHR,
+ EAC3_PASSTHR,
+ DTS_PASSTHR
+};
+/*
+List of transcoder's supported in the current usecases
+*/
+enum {
+ NO_TRANSCODER = 0,
+ AC3_TRANSCODER,
+ DTS_TRANSCODER
+};
+/*
+Requested end device format by user/app through set parameters
+*/
+enum {
+ UNCOMPRESSED = 0,
+ COMPRESSED,
+ COMPRESSED_CONVERT_EAC3_AC3,
+ COMPRESSED_CONVERT_ANY_AC3,
+ COMPRESSED_CONVERT_ANY_DTS,
+ AUTO_DEVICE_FORMAT,
+ UNCOMPRESSED_MCH, /* not to be exposed, internal use only */
+ COMPRESSED_CONVERT_AC3_ASSOC, /* not to be exposed, internal use only */
+ ALL_DEVICE_FORMATS
+};
+/*
+List of type of data routed on end device
+*/
+typedef enum {
+ ROUTE_NONE = 0x0,
+ ROUTE_UNCOMPRESSED = 0x1,
+ ROUTE_COMPRESSED = 0x2,
+ ROUTE_SW_TRANSCODED = 0x10, //route sub-format, not to be used directly
+ ROUTE_DSP_TRANSCODED = 0x20, //route sub-format, not to be used directly
+ ROUTE_MCH = 0x40, //route sub-format, not to be used directly
+ ROUTE_UNCOMPRESSED_MCH = (ROUTE_UNCOMPRESSED | ROUTE_MCH),
+ ROUTE_SW_TRANSCODED_COMPRESSED = (ROUTE_COMPRESSED | ROUTE_SW_TRANSCODED),
+ ROUTE_DSP_TRANSCODED_COMPRESSED = (ROUTE_COMPRESSED | ROUTE_DSP_TRANSCODED)
+}route_format_t;
+/*
+List of end device formats
+*/
+enum {
+ FORMAT_INVALID = -1,
+ FORMAT_PCM,
+ FORMAT_COMPR
+};
+/*
+Below are the only different types of decode that we perform
+*/
+enum {
+ DSP_DECODE = 1, // render uncompressed
+ DSP_PASSTHROUGH = 2, // render compressed
+ DSP_TRANSCODE = 4, // render as compressed
+ SW_DECODE = 8, // render as uncompressed
+ SW_DECODE_MCH = 16, // render as uncompressed
+ SW_PASSTHROUGH = 32, // render compressed
+ SW_TRANSCODE = 64, // render compressed
+ NUM_DECODE_PATH = 7
+};
+/*
+Modes of buffering that we can support
+As of now, we only support input buffering to an extent specified by usecase
+*/
+enum {
+ NO_BUFFERING_MODE = 0,
+ INPUT_BUFFERING_MODE,
+ OUTPUT_BUFFEING_MODE
+};
+/*
+playback controls
+*/
+enum {
+ PLAY = 1,
+ PAUSE = (1<<1),
+ RESUME = (1<<2),
+ SEEK = (1<<3),
+ EOS = (1<<4),
+ STOP = (1<<5),
+ STANDBY = (1<<6),
+ INIT = (1<<7),
+};
+/*
+Multiple instance of use case
+*/
+enum {
+ STEREO_DRIVER = 0,
+ MULTI_CHANNEL_DRIVER,
+ COMRPESSED_DRIVER,
+};
+/*
+Instance bits
+*/
+enum {
+ MULTI_CHANNEL_1_BIT = 1<<4,
+ MULTI_CHANNEL_2_BIT = 1<<5,
+ MULTI_CHANNEL_3_BIT = 1<<6,
+ COMPRESSED_1_BIT = 1<<12,
+ COMPRESSED_2_BIT = 1<<13,
+ COMPRESSED_3_BIT = 1<<14,
+ COMPRESSED_4_BIT = 1<<15,
+ COMPRESSED_5_BIT = 1<<16,
+ COMPRESSED_6_BIT = 1<<17
+};
+
+/*
+List of support formats configured from frameworks
+*/
+static const int supportedFormats[NUM_SUPPORTED_CODECS] = {
+ AUDIO_FORMAT_PCM_16_BIT,
+ AUDIO_FORMAT_PCM_24_BIT,
+ AUDIO_FORMAT_AAC,
+ AUDIO_FORMAT_HE_AAC_V1,
+ AUDIO_FORMAT_HE_AAC_V2,
+ AUDIO_FORMAT_AAC_ADIF,
+ AUDIO_FORMAT_AC3,
+ AUDIO_FORMAT_AC3_DM,
+ AUDIO_FORMAT_EAC3,
+ AUDIO_FORMAT_EAC3_DM,
+ AUDIO_FORMAT_DTS,
+ AUDIO_FORMAT_DTS_LBR,
+ AUDIO_FORMAT_MP3,
+ AUDIO_FORMAT_WMA,
+ AUDIO_FORMAT_WMA_PRO,
+ AUDIO_FORMAT_MP2
+};
+/*
+we can only have 6 types of decoder type stored with bit masks.
+*/
+static const int route_to_driver[NUM_DECODE_PATH][NUM_COLUMN_FOR_INDEXING] = {
+ {DSP_DECODE, ROUTE_UNCOMPRESSED_MCH},
+ {DSP_PASSTHROUGH, ROUTE_COMPRESSED},
+ {DSP_TRANSCODE, ROUTE_DSP_TRANSCODED_COMPRESSED},
+ {SW_DECODE, ROUTE_UNCOMPRESSED},
+ {SW_DECODE_MCH, ROUTE_UNCOMPRESSED_MCH},
+ {SW_PASSTHROUGH, ROUTE_COMPRESSED},
+ {SW_TRANSCODE, ROUTE_SW_TRANSCODED_COMPRESSED}
+};
+/*
+table to query index based on the format
+*/
+static const int format_index[NUM_SUPPORTED_CODECS][NUM_COLUMN_FOR_INDEXING] = {
+/*---------------------------------------------
+| FORMAT | INDEX |
+----------------------------------------------*/
+ {AUDIO_FORMAT_PCM_16_BIT, PCM_IDX},
+ {AUDIO_FORMAT_PCM_24_BIT, PCM_IDX},
+ {AUDIO_FORMAT_AAC, AAC_IDX},
+ {AUDIO_FORMAT_HE_AAC_V1, AAC_IDX},
+ {AUDIO_FORMAT_HE_AAC_V2, AAC_IDX},
+ {AUDIO_FORMAT_AAC_ADIF, AAC_IDX},
+ {AUDIO_FORMAT_AC3, AC3_IDX},
+ {AUDIO_FORMAT_AC3_DM, AC3_IDX},
+ {AUDIO_FORMAT_EAC3, EAC3_IDX},
+ {AUDIO_FORMAT_EAC3_DM, EAC3_IDX},
+ {AUDIO_FORMAT_DTS, DTS_IDX},
+ {AUDIO_FORMAT_DTS_LBR, DTS_LBR_IDX},
+ {AUDIO_FORMAT_MP3, MP3_IDX},
+ {AUDIO_FORMAT_WMA, WMA_IDX},
+ {AUDIO_FORMAT_WMA_PRO, WMA_PRO_IDX},
+ {AUDIO_FORMAT_MP2, MP2_IDX}
+};
+
+/*
+Table to query non HDMI and SPDIF devices and their states such as type of
+decode, type of data routed to end device and type of transcoding needed
+*/
+static const int usecase_decode_format[ALL_FORMATS_IDX*NUM_STATES_FOR_EACH_DEVICE_FMT] = {
+/*-----------------
+| UNCOMPR |
+-----------------*/
+/* PCM */
+ DSP_DECODE, //PCM_IDX
+ FORMAT_PCM, //ROUTE_FORMAT
+ NO_TRANSCODER,//TRANSCODE_FORMAT
+/* PCM */
+ SW_DECODE, // AAC_IDX
+ FORMAT_PCM, //ROUTE_FORMAT
+ NO_TRANSCODER,//TRANSCODE_FORMAT
+/* PCM */
+ SW_DECODE, //AC3_IDX
+ FORMAT_PCM, //ROUTE_FORMAT
+ NO_TRANSCODER,//TRANSCODE_FORMAT
+/* PCM */
+ SW_DECODE, //EAC3_IDX
+ FORMAT_PCM, //ROUTE_FORMAT
+ NO_TRANSCODER,//TRANSCODE_FORMAT
+/* PCM */
+ DSP_DECODE, //DTS_IDX
+ FORMAT_PCM, //ROUTE_FORMAT
+ NO_TRANSCODER,//TRANSCODE_FORMAT
+/* PCM */
+ DSP_DECODE, //DTS_LBR_IDX
+ FORMAT_PCM, //ROUTE_FORMAT
+ NO_TRANSCODER,//TRANSCODE_FORMAT
+/* PCM */
+ DSP_DECODE, //MP3_IDX
+ FORMAT_PCM, //ROUTE_FORMAT
+ NO_TRANSCODER,//TRANSCODE_FORMAT
+/* PCM */
+ DSP_DECODE, //WMA_IDX
+ FORMAT_PCM, //ROUTE_FORMAT
+ NO_TRANSCODER,//TRANSCODE_FORMAT
+/* PCM */
+ DSP_DECODE, //WMA_PRO_IDX
+ FORMAT_PCM, //ROUTE_FORMAT
+ NO_TRANSCODER,//TRANSCODE_FORMAT
+/* PCM */
+ DSP_DECODE, //MP2_IDX
+ FORMAT_PCM, //ROUTE_FORMAT
+ NO_TRANSCODER//TRANSCODE_FORMAT
+};
+/*
+Table to query HDMI and SPDIF devices and their states such as type of
+decode, type of data routed to end device and type of transcoding needed
+*/
+static const int usecase_docode_hdmi_spdif[ALL_FORMATS_IDX*NUM_STATES_FOR_EACH_DEVICE_FMT]
+ [ALL_DEVICE_FORMATS] = {
+/*-------------------------------------------------------------------------------------------------------------------------------------------------------
+| UNCOMPRESSED | COMPR | COMPR_CONV | COMPR_CONV | COMPR_CONV | AUTO | UNCOMPR_MCH | AC3_AC3 |
+| | | EAC3_AC3 | ANY_AC3 | ANY_DTS | | | |
+--------------------------------------------------------------------------------------------------------------------------------------------------------*/
+/* PCM PCM PCM PCM PCM PCM PCM PCM */
+ {DSP_DECODE, DSP_DECODE, DSP_DECODE, DSP_DECODE, DSP_DECODE|DSP_TRANSCODE, DSP_DECODE, DSP_DECODE, DSP_DECODE}, //PCM_IDX
+ {FORMAT_PCM, FORMAT_PCM, FORMAT_PCM, FORMAT_PCM, FORMAT_COMPR, FORMAT_PCM, FORMAT_PCM, FORMAT_PCM}, //ROUTE_FORMAT
+ {NO_TRANSCODER, NO_TRANSCODER, NO_TRANSCODER, NO_TRANSCODER, DTS_TRANSCODER, NO_TRANSCODER, NO_TRANSCODER, NO_TRANSCODER}, //TRANSCODE_FMT
+/* PCM PCM PCM AC3 PCM PCM PCM PCM */
+ {SW_DECODE, SW_DECODE, SW_DECODE, SW_TRANSCODE, DSP_DECODE, SW_DECODE, SW_DECODE_MCH, SW_DECODE}, //AAC_IDX
+ {FORMAT_PCM, FORMAT_PCM, FORMAT_PCM, FORMAT_COMPR, FORMAT_PCM, FORMAT_PCM, FORMAT_PCM, FORMAT_PCM}, //ROUTE_FORMAT
+ {NO_TRANSCODER, NO_TRANSCODER, NO_TRANSCODER, AC3_TRANSCODER, NO_TRANSCODER, NO_TRANSCODER, NO_TRANSCODER, NO_TRANSCODER}, //TRANSCODE_FMT
+/* PCM AC3 AC3 AC3 PCM AC3 PCM AC3 */
+ {SW_DECODE, SW_PASSTHROUGH, SW_PASSTHROUGH, SW_PASSTHROUGH, DSP_DECODE, SW_PASSTHROUGH, SW_DECODE_MCH, SW_TRANSCODE}, //AC3_IDX
+ {FORMAT_PCM, FORMAT_COMPR, FORMAT_COMPR, FORMAT_COMPR, FORMAT_PCM, FORMAT_COMPR, FORMAT_PCM, FORMAT_COMPR}, //ROUTE_FORMAT
+ {NO_TRANSCODER, AC3_PASSTHR, AC3_PASSTHR, AC3_PASSTHR, NO_TRANSCODER, AC3_PASSTHR, NO_TRANSCODER, AC3_TRANSCODER}, //TRANSCODE_FMT
+/* PCM EAC3 AC3 AC3 PCM EAC3 PCM PCM */
+ {SW_DECODE, SW_PASSTHROUGH, SW_TRANSCODE, SW_TRANSCODE, DSP_DECODE, SW_PASSTHROUGH, SW_DECODE_MCH, SW_TRANSCODE}, //EAC3_IDX
+ {FORMAT_PCM, FORMAT_COMPR, FORMAT_COMPR, FORMAT_COMPR, FORMAT_PCM, FORMAT_COMPR, FORMAT_PCM, FORMAT_COMPR}, //ROUTE_FORMAT
+ {NO_TRANSCODER, EAC3_PASSTHR, AC3_TRANSCODER, AC3_TRANSCODER, NO_TRANSCODER, EAC3_PASSTHR, NO_TRANSCODER, AC3_TRANSCODER}, //TRANSCODE_FMT
+/* PCM DTS PCM PCM DTS DTS PCM PCM */
+ {DSP_DECODE, DSP_PASSTHROUGH, DSP_DECODE, DSP_DECODE, DSP_PASSTHROUGH, DSP_PASSTHROUGH, DSP_DECODE, DSP_DECODE},//DTS_IDX
+ {FORMAT_PCM, FORMAT_COMPR, FORMAT_PCM, FORMAT_PCM, FORMAT_COMPR, FORMAT_COMPR, FORMAT_PCM, FORMAT_PCM}, //ROUTE_FORMAT
+ {NO_TRANSCODER, DTS_PASSTHR, NO_TRANSCODER, NO_TRANSCODER, DTS_PASSTHR, DTS_PASSTHR, NO_TRANSCODER, NO_TRANSCODER}, //TRANSCODE_FMT
+/* PCM DTS_LBR PCM PCM DTS DTS PCM PCM */
+ {DSP_DECODE, DSP_PASSTHROUGH, DSP_DECODE, DSP_DECODE, DSP_PASSTHROUGH, DSP_PASSTHROUGH, DSP_DECODE, DSP_DECODE},//DTS_LBR_IDX
+ {FORMAT_PCM, FORMAT_COMPR, FORMAT_PCM, FORMAT_PCM, FORMAT_COMPR, FORMAT_COMPR, FORMAT_PCM, FORMAT_PCM}, //ROUTE_FORMAT
+ {NO_TRANSCODER, DTS_PASSTHR, NO_TRANSCODER, NO_TRANSCODER, DTS_PASSTHR, DTS_PASSTHR, NO_TRANSCODER, NO_TRANSCODER}, //TRANSCODE_FMT
+/* PCM PCM PCM PCM DTS PCM PCM PCM */
+ {DSP_DECODE, DSP_DECODE, DSP_DECODE, DSP_DECODE, DSP_DECODE|DSP_TRANSCODE, DSP_DECODE, DSP_DECODE, DSP_DECODE}, //MP3_IDX
+ {FORMAT_PCM, FORMAT_PCM, FORMAT_PCM, FORMAT_PCM, FORMAT_COMPR, FORMAT_PCM, FORMAT_PCM, FORMAT_PCM}, //ROUTE_FORMAT
+ {NO_TRANSCODER, NO_TRANSCODER, NO_TRANSCODER, NO_TRANSCODER, DTS_TRANSCODER, NO_TRANSCODER, NO_TRANSCODER, NO_TRANSCODER}, //TRANSCODE_FMT
+/* PCM PCM PCM PCM DTS PCM PCM PCM */
+ {DSP_DECODE, DSP_DECODE, DSP_DECODE, DSP_DECODE, DSP_DECODE|DSP_TRANSCODE, DSP_DECODE, DSP_DECODE, DSP_DECODE}, //WMA_IDX
+ {FORMAT_PCM, FORMAT_PCM, FORMAT_PCM, FORMAT_PCM, FORMAT_COMPR, FORMAT_PCM, FORMAT_PCM, FORMAT_PCM}, //ROUTE_FORMAT
+ {NO_TRANSCODER, NO_TRANSCODER, NO_TRANSCODER, NO_TRANSCODER, DTS_TRANSCODER, NO_TRANSCODER, NO_TRANSCODER, NO_TRANSCODER}, //TRANSCODE_FMT
+/* PCM PCM PCM PCM DTS PCM PCM PCM */
+ {DSP_DECODE, DSP_DECODE, DSP_DECODE, DSP_DECODE, DSP_DECODE|DSP_TRANSCODE, DSP_DECODE, DSP_DECODE, DSP_DECODE}, //WMA_PRO_IDX
+ {FORMAT_PCM, FORMAT_PCM, FORMAT_PCM, FORMAT_PCM, FORMAT_COMPR, FORMAT_PCM, FORMAT_PCM, FORMAT_PCM}, //ROUTE_FORMAT
+ {NO_TRANSCODER, NO_TRANSCODER, NO_TRANSCODER, NO_TRANSCODER, DTS_TRANSCODER, NO_TRANSCODER, NO_TRANSCODER, NO_TRANSCODER}, //TRANSCODE_FMT
+/* PCM PCM PCM PCM DTS PCM PCM PCM */
+ {DSP_DECODE, DSP_DECODE, DSP_DECODE, DSP_DECODE, DSP_DECODE|DSP_TRANSCODE, DSP_DECODE, DSP_DECODE, DSP_DECODE}, //MP2_IDX
+ {FORMAT_PCM, FORMAT_PCM, FORMAT_PCM, FORMAT_PCM, FORMAT_COMPR, FORMAT_PCM, FORMAT_PCM, FORMAT_PCM}, //ROUTE_FORMAT
+ {NO_TRANSCODER, NO_TRANSCODER, NO_TRANSCODER, NO_TRANSCODER, DTS_TRANSCODER, NO_TRANSCODER, NO_TRANSCODER, NO_TRANSCODER} //TRANSCODE_FMT
+};
+/*
+List of decoders which require config as part of first buffer
+*/
+static const int decodersRequireConfig[] = {
+ AUDIO_FORMAT_AAC,
+ AUDIO_FORMAT_HE_AAC_V1,
+ AUDIO_FORMAT_HE_AAC_V2,
+ AUDIO_FORMAT_AAC_ADIF,
+ AUDIO_FORMAT_WMA,
+ AUDIO_FORMAT_WMA_PRO
+};
+/*
+List of enum that are used in Broadcast.
+NOTE: Need to be removed once broadcast is moved with updated states as above
+*/
+enum {
+ INVALID_FORMAT = -1,
+ PCM_FORMAT = 0,
+ COMPRESSED_FORMAT = 1,
+ COMPRESSED_FORCED_PCM_FORMAT = 2,
+ COMPRESSED_PASSTHROUGH_FORMAT = 3
+};
+
+
struct audio_bitstream_sm {
int buffering_factor;
int buffering_factor_cnt;
@@ -255,18 +638,33 @@
char *inp_buf;
char *inp_buf_curr_ptr;
char *inp_buf_write_ptr;
+ uint32_t inp_buf_size;
char *enc_out_buf;
char *enc_out_buf_write_ptr;
+ uint32_t enc_out_buf_size;
char *pcm_2_out_buf;
char *pcm_2_out_buf_write_ptr;
+ uint32_t pcm_2_out_buf_size;
char *pcm_mch_out_buf;
char *pcm_mch_out_buf_write_ptr;
+ uint32_t pcm_mch_out_buf_size;
char *passt_out_buf;
char *passt_out_buf_write_ptr;
+ uint32_t passt_out_buf_size;
+};
+
+/*
+Meta data structure for handling compressed output
+*/
+struct output_metadata {
+ uint32_t metadataLength;
+ uint32_t bufferLength;
+ uint64_t timestamp;
+ uint32_t reserved[12];
};
#endif // QCOM_AUDIO_PLATFORM_H
diff --git a/hal_mpq/platform_api.h b/hal_mpq/platform_api.h
index 44ad790..955aa3b 100644
--- a/hal_mpq/platform_api.h
+++ b/hal_mpq/platform_api.h
@@ -51,5 +51,7 @@
/* returns the latency for a usecase in Us */
int64_t platform_render_latency(audio_usecase_t usecase);
int platform_update_usecase_from_source(int source, audio_usecase_t usecase);
+audio_usecase_t platform_get_usecase(audio_usecase_stream_type_t uc_type);
+int platform_free_usecase(audio_usecase_t uc_id);
#endif // QCOM_AUDIO_PLATFORM_API_H
diff --git a/legacy/alsa_sound/ALSAControl.cpp b/legacy/alsa_sound/ALSAControl.cpp
index 2d610a1..5b2cf31 100644
--- a/legacy/alsa_sound/ALSAControl.cpp
+++ b/legacy/alsa_sound/ALSAControl.cpp
@@ -1,7 +1,7 @@
/* ALSAControl.cpp
**
** Copyright 2008-2009 Wind River Systems
- ** Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ ** Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
diff --git a/legacy/alsa_sound/ALSAStreamOps.cpp b/legacy/alsa_sound/ALSAStreamOps.cpp
index c7c0ca1..ad9a117 100644
--- a/legacy/alsa_sound/ALSAStreamOps.cpp
+++ b/legacy/alsa_sound/ALSAStreamOps.cpp
@@ -1,7 +1,7 @@
/* ALSAStreamOps.cpp
**
** Copyright 2008-2009 Wind River Systems
- ** Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ ** Copyright (c) 2011, The Linux Foundation. All rights reserved.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
diff --git a/legacy/alsa_sound/AudioHardwareALSA.cpp b/legacy/alsa_sound/AudioHardwareALSA.cpp
index 508418c..c61a3e8 100644
--- a/legacy/alsa_sound/AudioHardwareALSA.cpp
+++ b/legacy/alsa_sound/AudioHardwareALSA.cpp
@@ -1,7 +1,7 @@
/* AudioHardwareALSA.cpp
**
** Copyright 2008-2010 Wind River Systems
- ** Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ ** Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
diff --git a/legacy/alsa_sound/AudioHardwareALSA.h b/legacy/alsa_sound/AudioHardwareALSA.h
index 4ef878b..b65773a 100644
--- a/legacy/alsa_sound/AudioHardwareALSA.h
+++ b/legacy/alsa_sound/AudioHardwareALSA.h
@@ -1,7 +1,7 @@
/* AudioHardwareALSA.h
**
** Copyright 2008-2010, Wind River Systems
- ** Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ ** Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
diff --git a/legacy/alsa_sound/AudioPolicyManagerALSA.cpp b/legacy/alsa_sound/AudioPolicyManagerALSA.cpp
index 93c9b01..36ae4d3 100644
--- a/legacy/alsa_sound/AudioPolicyManagerALSA.cpp
+++ b/legacy/alsa_sound/AudioPolicyManagerALSA.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2009 The Android Open Source Project
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/legacy/alsa_sound/AudioPolicyManagerALSA.h b/legacy/alsa_sound/AudioPolicyManagerALSA.h
index 91b7e13..a343cff 100644
--- a/legacy/alsa_sound/AudioPolicyManagerALSA.h
+++ b/legacy/alsa_sound/AudioPolicyManagerALSA.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2009 The Android Open Source Project
- * Copyright (C) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (C) 2011-2012, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/legacy/alsa_sound/AudioStreamInALSA.cpp b/legacy/alsa_sound/AudioStreamInALSA.cpp
index 4771d42..7887f55 100644
--- a/legacy/alsa_sound/AudioStreamInALSA.cpp
+++ b/legacy/alsa_sound/AudioStreamInALSA.cpp
@@ -1,7 +1,7 @@
/* AudioStreamInALSA.cpp
**
** Copyright 2008-2009 Wind River Systems
- ** Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ ** Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
diff --git a/legacy/alsa_sound/AudioStreamOutALSA.cpp b/legacy/alsa_sound/AudioStreamOutALSA.cpp
index 2adb5d8..bbb8d3d 100644
--- a/legacy/alsa_sound/AudioStreamOutALSA.cpp
+++ b/legacy/alsa_sound/AudioStreamOutALSA.cpp
@@ -1,7 +1,7 @@
/* AudioStreamOutALSA.cpp
**
** Copyright 2008-2009 Wind River Systems
- ** Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ ** Copyright (c) 2011, The Linux Foundation. All rights reserved.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
diff --git a/legacy/alsa_sound/AudioUsbALSA.cpp b/legacy/alsa_sound/AudioUsbALSA.cpp
index 3316e3e..93e0754 100644
--- a/legacy/alsa_sound/AudioUsbALSA.cpp
+++ b/legacy/alsa_sound/AudioUsbALSA.cpp
@@ -1,5 +1,5 @@
/* AudioUsbALSA.cpp
-Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+Copyright (c) 2012, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
@@ -10,7 +10,7 @@
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 Code Aurora Forum, Inc. nor the names of its
+ * Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
diff --git a/legacy/alsa_sound/AudioUsbALSA.h b/legacy/alsa_sound/AudioUsbALSA.h
index 4204eb0..d06bbb7 100644
--- a/legacy/alsa_sound/AudioUsbALSA.h
+++ b/legacy/alsa_sound/AudioUsbALSA.h
@@ -1,6 +1,6 @@
/* AudioUsbALSA.h
-Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+Copyright (c) 2012, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
@@ -11,7 +11,7 @@
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 Code Aurora Forum, Inc. nor the names of its
+ * Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
diff --git a/legacy/alsa_sound/alsa_default.cpp b/legacy/alsa_sound/alsa_default.cpp
index 2f043bb..5be2958 100644
--- a/legacy/alsa_sound/alsa_default.cpp
+++ b/legacy/alsa_sound/alsa_default.cpp
@@ -1,7 +1,7 @@
/* alsa_default.cpp
**
** Copyright 2009 Wind River Systems
- ** Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ ** Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
diff --git a/legacy/alsa_sound/audio_hw_hal.cpp b/legacy/alsa_sound/audio_hw_hal.cpp
index ab15e27..24e50d3 100644
--- a/legacy/alsa_sound/audio_hw_hal.cpp
+++ b/legacy/alsa_sound/audio_hw_hal.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2011 The Android Open Source Project
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -770,7 +770,7 @@
hal_api_version: HARDWARE_HAL_API_VERSION,
id: AUDIO_HARDWARE_MODULE_ID,
name: "QCOM Audio HW HAL",
- author: "Code Aurora Forum",
+ author: "The Linux Foundation",
methods: &qcom_audio_module_methods,
dso : NULL,
reserved : {0},
diff --git a/legacy/alsa_sound/audio_policy_hal.cpp b/legacy/alsa_sound/audio_policy_hal.cpp
index 5363e28..a1687f7 100644
--- a/legacy/alsa_sound/audio_policy_hal.cpp
+++ b/legacy/alsa_sound/audio_policy_hal.cpp
@@ -455,7 +455,7 @@
version_minor: 0,
id: AUDIO_POLICY_HARDWARE_MODULE_ID,
name: "QCOM Audio Policy HAL",
- author: "Code Aurora Forum",
+ author: "The Linux Foundation",
methods: &qcom_ap_module_methods,
dso : NULL,
reserved : {0},
diff --git a/legacy/libalsa-intf/alsa_audio.h b/legacy/libalsa-intf/alsa_audio.h
index 7f2acf0..90fbe56 100644
--- a/legacy/libalsa-intf/alsa_audio.h
+++ b/legacy/libalsa-intf/alsa_audio.h
@@ -1,6 +1,6 @@
/*
** Copyright 2010, The Android Open-Source Project
-** Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+** Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
diff --git a/legacy/libalsa-intf/alsa_mixer.c b/legacy/libalsa-intf/alsa_mixer.c
index cdcdcea..c3738f0 100644
--- a/legacy/libalsa-intf/alsa_mixer.c
+++ b/legacy/libalsa-intf/alsa_mixer.c
@@ -1,6 +1,6 @@
/*
** Copyright 2010, The Android Open-Source Project
-** Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+** Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
diff --git a/legacy/libalsa-intf/alsa_pcm.c b/legacy/libalsa-intf/alsa_pcm.c
index a814ae8..51c5691 100644
--- a/legacy/libalsa-intf/alsa_pcm.c
+++ b/legacy/libalsa-intf/alsa_pcm.c
@@ -1,6 +1,6 @@
/*
** Copyright 2010, The Android Open-Source Project
-** Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+** Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
diff --git a/legacy/libalsa-intf/alsa_ucm.c b/legacy/libalsa-intf/alsa_ucm.c
index e53211f..fac8498 100644
--- a/legacy/libalsa-intf/alsa_ucm.c
+++ b/legacy/libalsa-intf/alsa_ucm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -10,7 +10,7 @@
* 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 Code Aurora Forum, Inc. nor the names of its
+ * * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
diff --git a/legacy/libalsa-intf/alsaucm_test.c b/legacy/libalsa-intf/alsaucm_test.c
index e01cf59..aaed38e 100644
--- a/legacy/libalsa-intf/alsaucm_test.c
+++ b/legacy/libalsa-intf/alsaucm_test.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -10,7 +10,7 @@
* 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 Code Aurora Forum, Inc. nor the names of its
+ * * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
diff --git a/legacy/libalsa-intf/amix.c b/legacy/libalsa-intf/amix.c
index 40f3807..b425ed5 100644
--- a/legacy/libalsa-intf/amix.c
+++ b/legacy/libalsa-intf/amix.c
@@ -1,6 +1,6 @@
/*
** Copyright 2010, The Android Open-Source Project
-** Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+** Copyright (c) 2011, The Linux Foundation. All rights reserved.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
diff --git a/legacy/libalsa-intf/aplay.c b/legacy/libalsa-intf/aplay.c
index c060277..120febd 100644
--- a/legacy/libalsa-intf/aplay.c
+++ b/legacy/libalsa-intf/aplay.c
@@ -1,6 +1,6 @@
/*
** Copyright 2010, The Android Open-Source Project
-** Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+** Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
diff --git a/legacy/libalsa-intf/arec.c b/legacy/libalsa-intf/arec.c
index cab88f1..30e710c 100644
--- a/legacy/libalsa-intf/arec.c
+++ b/legacy/libalsa-intf/arec.c
@@ -1,6 +1,6 @@
/*
** Copyright 2010, The Android Open-Source Project
-** Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+** Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
diff --git a/legacy/libalsa-intf/msm8960_use_cases.h b/legacy/libalsa-intf/msm8960_use_cases.h
index 4c37cd0..7f98df1 100644
--- a/legacy/libalsa-intf/msm8960_use_cases.h
+++ b/legacy/libalsa-intf/msm8960_use_cases.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -10,7 +10,7 @@
* 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 Code Aurora Forum, Inc. nor the names of its
+ * * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
diff --git a/mm-audio/aenc-aac/Android.mk b/mm-audio/aenc-aac/Android.mk
index 8698436..8ab45b3 100644
--- a/mm-audio/aenc-aac/Android.mk
+++ b/mm-audio/aenc-aac/Android.mk
@@ -21,6 +21,9 @@
ifeq ($(call is-board-platform,apq8084),true)
include $(AENC_AAC_PATH)/qdsp6/Android.mk
endif
+ifeq ($(call is-board-platform,mpq8092),true)
+include $(AENC_AAC_PATH)/qdsp6/Android.mk
+endif
endif
diff --git a/mm-audio/aenc-amrnb/Android.mk b/mm-audio/aenc-amrnb/Android.mk
index 6c2f458..2601ede 100644
--- a/mm-audio/aenc-amrnb/Android.mk
+++ b/mm-audio/aenc-amrnb/Android.mk
@@ -21,6 +21,9 @@
ifeq ($(call is-board-platform,apq8084),true)
include $(AENC_AMR_PATH)/qdsp6/Android.mk
endif
+ifeq ($(call is-board-platform,mpq8092),true)
+include $(AENC_AMR_PATH)/qdsp6/Android.mk
+endif
endif
diff --git a/mm-audio/aenc-evrc/Android.mk b/mm-audio/aenc-evrc/Android.mk
index c8ee1ed..2f42d6b 100644
--- a/mm-audio/aenc-evrc/Android.mk
+++ b/mm-audio/aenc-evrc/Android.mk
@@ -21,6 +21,9 @@
ifeq ($(call is-board-platform,apq8084),true)
include $(AENC_EVRC_PATH)/qdsp6/Android.mk
endif
+ifeq ($(call is-board-platform,mpq8092),true)
+include $(AENC_EVRC_PATH)/qdsp6/Android.mk
+endif
endif
diff --git a/mm-audio/aenc-qcelp13/Android.mk b/mm-audio/aenc-qcelp13/Android.mk
index 8f6985c..fe18efc 100644
--- a/mm-audio/aenc-qcelp13/Android.mk
+++ b/mm-audio/aenc-qcelp13/Android.mk
@@ -21,6 +21,8 @@
ifeq ($(call is-board-platform,apq8084),true)
include $(AENC_QCELP13_PATH)/qdsp6/Android.mk
endif
-
+ifeq ($(call is-board-platform,mpq8092),true)
+include $(AENC_QCELP13_PATH)/qdsp6/Android.mk
+endif
endif
diff --git a/policy_hal/AudioPolicyManager.cpp b/policy_hal/AudioPolicyManager.cpp
index 0716656..4fa2356 100644
--- a/policy_hal/AudioPolicyManager.cpp
+++ b/policy_hal/AudioPolicyManager.cpp
@@ -27,9 +27,6 @@
#define ALOGVV(a...) do { } while(0)
#endif
-// A device mask for all audio input devices that are considered "virtual" when evaluating
-// active inputs in getActiveInput()
-#define APM_AUDIO_IN_DEVICE_VIRTUAL_ALL AUDIO_DEVICE_IN_REMOTE_SUBMIX | AUDIO_DEVICE_IN_FM_RX_A2DP
// A device mask for all audio output devices that are considered "remote" when evaluating
// active output devices in isStreamActiveRemotely()
#define APM_AUDIO_OUT_DEVICE_REMOTE_ALL AUDIO_DEVICE_OUT_REMOTE_SUBMIX
@@ -739,16 +736,6 @@
return device;
}
-bool AudioPolicyManager::isVirtualInputDevice(audio_devices_t device)
-{
- if ((device & AUDIO_DEVICE_BIT_IN) != 0) {
- device &= ~AUDIO_DEVICE_BIT_IN;
- if ((popcount(device) == 1) && ((device & ~APM_AUDIO_IN_DEVICE_VIRTUAL_ALL) == 0))
- return true;
- }
- return false;
-}
-
AudioPolicyManager::device_category AudioPolicyManager::getDeviceCategory(audio_devices_t device)
{
switch(getDeviceForVolume(device)) {
diff --git a/policy_hal/AudioPolicyManager.h b/policy_hal/AudioPolicyManager.h
index 2e0c6fb..7a8cfa9 100644
--- a/policy_hal/AudioPolicyManager.h
+++ b/policy_hal/AudioPolicyManager.h
@@ -68,8 +68,6 @@
// select input device corresponding to requested audio source
virtual audio_devices_t getDeviceForInputSource(int inputSource);
- static bool isVirtualInputDevice(audio_devices_t device);
-
// compute the actual volume for a given stream according to the requested index and a particular
// device
virtual float computeVolume(int stream, int index, audio_io_handle_t output, audio_devices_t device);