mpq8092: Add bitstream files
Add bitstream files
Change-Id: I002b2fe4249ffc28665b7efc80d9a5d7ad90ea74
diff --git a/hal_mpq/Android.mk b/hal_mpq/Android.mk
index 24fca4e..683de7a 100644
--- a/hal_mpq/Android.mk
+++ b/hal_mpq/Android.mk
@@ -11,6 +11,7 @@
LOCAL_SRC_FILES := \
audio_hw.c \
audio_stream_out.c \
+ audio_bitstream_sm.c \
$(AUDIO_PLATFORM)/hw_info.c \
$(AUDIO_PLATFORM)/platform.c
diff --git a/hal_mpq/audio_bitstream_sm.c b/hal_mpq/audio_bitstream_sm.c
new file mode 100644
index 0000000..9f2564d
--- /dev/null
+++ b/hal_mpq/audio_bitstream_sm.c
@@ -0,0 +1,445 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <dlfcn.h>
+#include <math.h>
+
+#define LOG_TAG "AudioBitstreamStateMachine"
+//#define LOG_NDEBUG 0
+#define LOG_NDDEBUG 0
+#include <utils/Log.h>
+
+#include <cutils/properties.h>
+#include "audio_hw.h"
+#include "platform_api.h"
+#include <platform.h>
+// ----------------------------------------------------------------------------
+
+
+/*
+Initialize all input and output pointers
+Allocate twice the max buffer size of input and output for sufficient buffering
+*/
+int audio_bitstream_init(struct audio_bitstream_sm *bstream, int buffering_factor)
+{
+ bstream->buffering_factor = buffering_factor;
+ bstream->buffering_factor_cnt = 0;
+
+ 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");
+ return 0;
+ }
+
+ bstream->enc_out_buf =(char *)malloc(SAMPLES_PER_CHANNEL*
+ MAX_INPUT_CHANNELS_SUPPORTED*
+ FACTOR_FOR_BUFFERING);
+ if(bstream->enc_out_buf) {
+ bstream->enc_out_buf_write_ptr = bstream->enc_out_buf;
+ } else {
+ ALOGE("MS11 Enc output buffer not allocated");
+ return 0;
+ }
+ bstream->pcm_2_out_buf =(char *)malloc(SAMPLES_PER_CHANNEL*STEREO_CHANNELS *
+ FACTOR_FOR_BUFFERING);
+ 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");
+ return 0;
+ }
+ bstream->pcm_mch_out_buf =(char *)malloc(SAMPLES_PER_CHANNEL *
+ MAX_OUTPUT_CHANNELS_SUPPORTED *
+ FACTOR_FOR_BUFFERING);
+ 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");
+ return 0;
+ }
+ bstream->passt_out_buf =(char *)malloc(SAMPLES_PER_CHANNEL *
+ MAX_INPUT_CHANNELS_SUPPORTED *
+ FACTOR_FOR_BUFFERING);
+ if(bstream->passt_out_buf) {
+ bstream->passt_out_buf_write_ptr = bstream->passt_out_buf;
+ } else {
+ ALOGE("MS11 Enc output buffer not allocated");
+ return 0;
+ }
+ return 1;
+}
+
+/*
+Free the allocated memory
+*/
+int audio_bitstream_close(struct audio_bitstream_sm *bstream)
+{
+ if(bstream->inp_buf != NULL) {
+ free(bstream->inp_buf);
+ bstream->inp_buf = NULL;
+ }
+ if(bstream->enc_out_buf != NULL) {
+ free(bstream->enc_out_buf);
+ bstream->enc_out_buf = NULL;
+ }
+ if(bstream->pcm_2_out_buf != NULL) {
+ free(bstream->pcm_2_out_buf);
+ bstream->pcm_2_out_buf = NULL;
+ }
+ if(bstream->pcm_mch_out_buf != NULL) {
+ free(bstream->pcm_mch_out_buf);
+ bstream->pcm_mch_out_buf = NULL;
+ }
+ if(bstream->passt_out_buf != NULL) {
+ free(bstream->passt_out_buf);
+ bstream->passt_out_buf = NULL;
+ }
+ bstream->buffering_factor = 1;
+ bstream->buffering_factor_cnt = 0;
+ return 0;
+}
+
+/*
+Reset the buffer pointers to start for. This will be help in flush and close
+*/
+void audio_bitstream_reset_ptr( struct audio_bitstream_sm *bstream)
+{
+ bstream->inp_buf_curr_ptr = bstream->inp_buf_write_ptr = bstream->inp_buf;
+ bstream->enc_out_buf_write_ptr = bstream->enc_out_buf;
+ bstream->pcm_2_out_buf_write_ptr = bstream->pcm_2_out_buf;
+ bstream->pcm_mch_out_buf_write_ptr = bstream->pcm_mch_out_buf;
+ bstream->passt_out_buf_write_ptr = bstream->passt_out_buf;
+ bstream->buffering_factor_cnt = 0;
+}
+
+/*
+Reset the output buffer pointers to start for port reconfiguration
+*/
+void audio_bitstream_reset_output_bitstream_ptr(
+ struct audio_bitstream_sm *bstream)
+{
+ bstream->enc_out_buf_write_ptr = bstream->enc_out_buf;
+ bstream->pcm_2_out_buf_write_ptr = bstream->pcm_2_out_buf;
+ bstream->pcm_mch_out_buf_write_ptr = bstream->pcm_mch_out_buf;
+ bstream->passt_out_buf_write_ptr = bstream->passt_out_buf;
+}
+
+/*
+Copy the bitstream/pcm from Player to internal buffer.
+The incoming bitstream is appended to existing bitstream
+*/
+void audio_bitstream_copy_to_internal_buffer(
+ 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) ) {
+ ALOGE("Input bitstream is not consumed");
+ return;
+ }
+
+ memcpy(bstream->inp_buf_write_ptr, buf_ptr, bytes);
+ bstream->inp_buf_write_ptr += bytes;
+ if(bstream->buffering_factor_cnt < bstream->buffering_factor)
+ bstream->buffering_factor_cnt++;
+}
+
+/*
+Append zeros to the bitstream, so that the entire bitstream in ADIF is pushed
+out for decoding
+*/
+void audio_bitstream_append_silence_internal_buffer(
+ struct audio_bitstream_sm *bstream,
+ uint32_t bytes, unsigned char value)
+{
+ int32_t bufLen = SAMPLES_PER_CHANNEL*MAX_INPUT_CHANNELS_SUPPORTED*
+ (bstream->buffering_factor+1);
+ uint32_t i = 0;
+ if( (bstream->inp_buf_write_ptr+bytes) > (bstream->inp_buf+bufLen) ) {
+ bytes = bufLen + bstream->inp_buf - bstream->inp_buf_write_ptr;
+ }
+ for(i=0; i< bytes; i++)
+ *bstream->inp_buf_write_ptr++ = value;
+ if(bstream->buffering_factor_cnt < bstream->buffering_factor)
+ bstream->buffering_factor_cnt++;
+}
+
+/*
+Flags if sufficient bitstream is available to proceed to decode based on
+the threshold
+*/
+int audio_bitstream_sufficient_buffer_to_decode(
+ struct audio_bitstream_sm *bstream,
+ int min_bytes_to_decode)
+{
+ int proceed_decode = 0;
+ if( (bstream->inp_buf_write_ptr -\
+ bstream->inp_buf_curr_ptr) > min_bytes_to_decode)
+ proceed_decode = 1;
+ return proceed_decode;
+}
+
+/*
+Gets the start address of the bitstream buffer. This is used for start of decode
+*/
+char* audio_bitstream_get_input_buffer_ptr(
+ struct audio_bitstream_sm *bstream)
+{
+ return bstream->inp_buf_curr_ptr;
+}
+
+/*
+Gets the writePtr of the bitstream buffer. This is used for calculating length of
+bitstream
+*/
+char* audio_bitstream_get_input_buffer_write_ptr(
+ struct audio_bitstream_sm *bstream)
+{
+ return bstream->inp_buf_write_ptr;
+}
+
+/*
+Get the output buffer start pointer to start rendering the pcm sampled to driver
+*/
+char* audio_bitstream_get_output_buffer_ptr(
+ struct audio_bitstream_sm *bstream,
+ int format)
+{
+ switch(format) {
+ case PCM_MCH_OUT:
+ return bstream->pcm_mch_out_buf;
+ case PCM_2CH_OUT:
+ return bstream->pcm_2_out_buf;
+ case COMPRESSED_OUT:
+ return bstream->enc_out_buf;
+ case TRANSCODE_OUT:
+ return bstream->passt_out_buf;
+ default:
+ return NULL;
+ }
+}
+
+/*
+Output the pointer from where the next PCM samples can be copied to buffer
+*/
+char* audio_bitstream_get_output_buffer_write_ptr(
+ struct audio_bitstream_sm *bstream,
+ int format)
+{
+ switch(format) {
+ case PCM_MCH_OUT:
+ return bstream->pcm_mch_out_buf_write_ptr;
+ case PCM_2CH_OUT:
+ return bstream->pcm_2_out_buf_write_ptr;
+ case COMPRESSED_OUT:
+ return bstream->enc_out_buf_write_ptr;
+ case TRANSCODE_OUT:
+ return bstream->passt_out_buf_write_ptr;
+ default:
+ return NULL;
+ }
+}
+
+/*
+Provides the bitstream size available in the internal buffer
+*/
+size_t audio_bitstream_get_size(struct audio_bitstream_sm *bstream)
+{
+ return (bstream->inp_buf_write_ptr-bstream->inp_buf_curr_ptr);
+}
+
+/*
+After decode, the residue bitstream in the buffer is moved to start, so as to
+avoid circularity constraints
+*/
+void audio_bitstream_copy_residue_to_start(
+ struct audio_bitstream_sm *bstream,
+ size_t bytes_consumed_in_decode)
+{
+ size_t remaining_curr_valid_bytes = bstream->inp_buf_write_ptr -
+ (bytes_consumed_in_decode+bstream->inp_buf_curr_ptr);
+ size_t remainingTotalBytes = bstream->inp_buf_write_ptr -
+ (bytes_consumed_in_decode+bstream->inp_buf);
+ if(bstream->buffering_factor_cnt == bstream->buffering_factor) {
+ memcpy(bstream->inp_buf, bstream->inp_buf+bytes_consumed_in_decode, remainingTotalBytes);
+ bstream->inp_buf_write_ptr = bstream->inp_buf+remainingTotalBytes;
+ bstream->inp_buf_curr_ptr = bstream->inp_buf_write_ptr-remaining_curr_valid_bytes;
+ } else {
+ bstream->inp_buf_curr_ptr += bytes_consumed_in_decode;
+ }
+}
+
+/*
+Remaing samples less than the one period size required for the pcm driver
+is moved to start of the buffer
+*/
+void audio_bitstream_copy_residue_output_start(
+ struct audio_bitstream_sm *bstream,
+ int format,
+ size_t samplesRendered)
+{
+ size_t remaining_bytes;
+ switch(format) {
+ case PCM_MCH_OUT:
+ remaining_bytes = bstream->pcm_mch_out_buf_write_ptr-\
+ (bstream->pcm_mch_out_buf+samplesRendered);
+ memcpy(bstream->pcm_mch_out_buf,
+ bstream->pcm_mch_out_buf+samplesRendered,
+ remaining_bytes);
+ bstream->pcm_mch_out_buf_write_ptr = \
+ bstream->pcm_mch_out_buf + remaining_bytes;
+ break;
+ case PCM_2CH_OUT:
+ remaining_bytes = bstream->pcm_2_out_buf_write_ptr-\
+ (bstream->pcm_2_out_buf+samplesRendered);
+ memcpy(bstream->pcm_2_out_buf,
+ bstream->pcm_2_out_buf+samplesRendered,
+ remaining_bytes);
+ bstream->pcm_2_out_buf_write_ptr = \
+ bstream->pcm_2_out_buf + remaining_bytes;
+ break;
+ case COMPRESSED_OUT:
+ remaining_bytes = bstream->enc_out_buf_write_ptr-\
+ (bstream->enc_out_buf+samplesRendered);
+ memcpy(bstream->enc_out_buf,
+ bstream->enc_out_buf+samplesRendered,
+ remaining_bytes);
+ bstream->enc_out_buf_write_ptr = \
+ bstream->enc_out_buf + remaining_bytes;
+ break;
+ case TRANSCODE_OUT:
+ remaining_bytes = bstream->passt_out_buf_write_ptr-\
+ (bstream->passt_out_buf+samplesRendered);
+ memcpy(bstream->passt_out_buf,
+ bstream->passt_out_buf+samplesRendered,
+ remaining_bytes);
+ bstream->passt_out_buf_write_ptr = \
+ bstream->passt_out_buf + remaining_bytes;
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+The write pointer is updated after the incoming PCM samples are copied to the
+output buffer
+*/
+void audio_bitstream_set_output_buffer_write_ptr(
+ struct audio_bitstream_sm *bstream,
+ int format, size_t output_pcm_sample)
+{
+ int alloc_bytes;
+ switch(format) {
+ case PCM_MCH_OUT:
+ alloc_bytes = SAMPLES_PER_CHANNEL*\
+ MAX_OUTPUT_CHANNELS_SUPPORTED*FACTOR_FOR_BUFFERING;
+ if (bstream->pcm_mch_out_buf + alloc_bytes >\
+ bstream->pcm_mch_out_buf_write_ptr + output_pcm_sample)
+ bstream->pcm_mch_out_buf_write_ptr += output_pcm_sample;
+ break;
+ case PCM_2CH_OUT:
+ alloc_bytes = SAMPLES_PER_CHANNEL*STEREO_CHANNELS*FACTOR_FOR_BUFFERING;
+ if(bstream->pcm_2_out_buf + alloc_bytes > \
+ bstream->pcm_2_out_buf_write_ptr + output_pcm_sample)
+ bstream->pcm_2_out_buf_write_ptr += output_pcm_sample;
+ break;
+ case COMPRESSED_OUT:
+ alloc_bytes = SAMPLES_PER_CHANNEL*\
+ MAX_INPUT_CHANNELS_SUPPORTED*FACTOR_FOR_BUFFERING;
+ if (bstream->enc_out_buf + alloc_bytes > \
+ bstream->enc_out_buf_write_ptr + output_pcm_sample)
+ bstream->enc_out_buf_write_ptr += output_pcm_sample;
+ break;
+ case TRANSCODE_OUT:
+ alloc_bytes = SAMPLES_PER_CHANNEL*\
+ MAX_INPUT_CHANNELS_SUPPORTED*FACTOR_FOR_BUFFERING;
+ if (bstream->passt_out_buf + alloc_bytes > \
+ bstream->passt_out_buf_write_ptr + output_pcm_sample)
+ bstream->passt_out_buf_write_ptr += output_pcm_sample;
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+Flags if sufficient samples are available to render to PCM driver
+*/
+int audio_bitstream_sufficient_sample_to_render(
+ struct audio_bitstream_sm *bstream,
+ int format, int mid_size_reqd)
+{
+ int status = 0;
+ char *buf_ptr = NULL, *buf_write_ptr = NULL;
+ switch(format) {
+ case PCM_MCH_OUT:
+ buf_ptr = bstream->pcm_mch_out_buf;
+ buf_write_ptr = bstream->pcm_mch_out_buf_write_ptr;
+ break;
+ case PCM_2CH_OUT:
+ buf_ptr = bstream->pcm_2_out_buf;
+ buf_write_ptr = bstream->pcm_2_out_buf_write_ptr;
+ break;
+ case COMPRESSED_OUT:
+ buf_ptr = bstream->enc_out_buf;
+ buf_write_ptr = bstream->enc_out_buf_write_ptr;
+ break;
+ case TRANSCODE_OUT:
+ buf_ptr = bstream->passt_out_buf;
+ buf_write_ptr = bstream->passt_out_buf_write_ptr;
+ break;
+ default:
+ break;
+ }
+ if( (buf_write_ptr-buf_ptr) >= mid_size_reqd )
+ status = 1;
+ return status;
+}
+
+void audio_bitstream_start_input_buffering_mode(
+ struct audio_bitstream_sm *bstream)
+{
+ bstream->buffering_factor_cnt = 0;
+}
+
+void audio_bitstream_stop_input_buffering_mode(
+ struct audio_bitstream_sm *bstream)
+{
+ size_t remaining_curr_valid_bytes = \
+ bstream->inp_buf_write_ptr - bstream->inp_buf_curr_ptr;
+ bstream->buffering_factor_cnt = bstream->buffering_factor;
+ memcpy(bstream->inp_buf,
+ bstream->inp_buf_curr_ptr,
+ remaining_curr_valid_bytes);
+ bstream->inp_buf_curr_ptr = bstream->inp_buf;
+ bstream->inp_buf_write_ptr = bstream->inp_buf + remaining_curr_valid_bytes;
+}
diff --git a/hal_mpq/audio_bitstream_sm.h b/hal_mpq/audio_bitstream_sm.h
new file mode 100644
index 0000000..db03bf5
--- /dev/null
+++ b/hal_mpq/audio_bitstream_sm.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef QCOM_AUDIO_BITSTRM_SM_H
+#define QCOM_AUDIO_BITSTRM_SM_H
+int audio_bitstream_init(struct audio_bitstream_sm *bstream, int buffering_factor);
+int audio_bitstream_close(struct audio_bitstream_sm *bstream);
+int audio_bitstream_with_buffering_factor(struct audio_bitstream_sm *bstream,
+ int in_buffering_factor);
+void audio_bitstream_reset_ptr( struct audio_bitstream_sm *bstream);
+void audio_bitstream_reset_output_bitstream_ptr(
+ struct audio_bitstream_sm *bstream);
+void audio_bitstream_copy_to_internal_buffer(
+ struct audio_bitstream_sm *bstream,
+ char *buf_ptr, size_t bytes);
+void audio_bitstream_append_silence_internal_buffer(
+ struct audio_bitstream_sm *bstream,
+ uint32_t bytes, unsigned char value);
+int audio_bitstream_sufficient_buffer_to_decode(
+ struct audio_bitstream_sm *bstream,
+ int min_bytes_to_decode);
+char* audio_bitstream_get_input_buffer_ptr(
+ struct audio_bitstream_sm *bstream);
+char* audio_bitstream_get_input_buffer_write_ptr(
+ struct audio_bitstream_sm *bstream);
+char* audio_bitstream_get_output_buffer_ptr(
+ struct audio_bitstream_sm *bstream,
+ int format);
+char* audio_bitstream_get_output_buffer_write_ptr(
+ struct audio_bitstream_sm *bstream,
+ int format);
+size_t audio_bitstream_get_size(struct audio_bitstream_sm *bstream);
+void audio_bitstream_copy_residue_to_start(
+ struct audio_bitstream_sm *bstream,
+ size_t bytes_consumed_in_decode);
+void audio_bitstream_copy_residue_output_start(
+ struct audio_bitstream_sm *bstream,
+ int format,
+ size_t samplesRendered);
+void audio_bitstream_set_output_buffer_write_ptr(
+ struct audio_bitstream_sm *bstream,
+ int format, size_t output_pcm_sample);
+int audio_bitstream_sufficient_sample_to_render(
+ struct audio_bitstream_sm *bstream,
+ int format, int mid_size_reqd);
+void audio_bitstream_start_input_buffering_mode(
+ struct audio_bitstream_sm *bstream);
+void audio_bitstream_stop_input_buffering_mode(
+ struct audio_bitstream_sm *bstream);
+#endif
diff --git a/hal_mpq/mpq8092/platform.h b/hal_mpq/mpq8092/platform.h
index 3cd56cf..7559258 100644
--- a/hal_mpq/mpq8092/platform.h
+++ b/hal_mpq/mpq8092/platform.h
@@ -177,11 +177,7 @@
#define PLAYBACK_OFFLOAD_DEVICE 9
#define COMPRESS_VOIP_CALL_PCM_DEVICE 3
-#ifdef PLATFORM_MSM8610
-#define LOWLATENCY_PCM_DEVICE 12
-#else
#define LOWLATENCY_PCM_DEVICE 15
-#endif
#define COMPRESS_CAPTURE_DEVICE 19
#ifdef PLATFORM_MSM8x26
@@ -239,4 +235,38 @@
void hw_info_append_hw_type(void *hw_info, snd_device_t snd_device,
char *device_name);
+#define SAMPLES_PER_CHANNEL 1536*2
+#define MAX_INPUT_CHANNELS_SUPPORTED 8
+#define FACTOR_FOR_BUFFERING 2
+#define STEREO_CHANNELS 2
+#define MAX_OUTPUT_CHANNELS_SUPPORTED 8
+
+#define PCM_2CH_OUT 0
+#define PCM_MCH_OUT 1
+#define SPDIF_OUT 2
+#define COMPRESSED_OUT 2 // should be same as SPDIF_OUT
+#define TRANSCODE_OUT 3
+#define FACTOR_FOR_BUFFERING 2
+
+struct audio_bitstream_sm {
+ int buffering_factor;
+ int buffering_factor_cnt;
+ // Buffer pointers for input and output
+ char *inp_buf;
+ char *inp_buf_curr_ptr;
+ char *inp_buf_write_ptr;
+
+ char *enc_out_buf;
+ char *enc_out_buf_write_ptr;
+
+ char *pcm_2_out_buf;
+ char *pcm_2_out_buf_write_ptr;
+
+ char *pcm_mch_out_buf;
+ char *pcm_mch_out_buf_write_ptr;
+
+ char *passt_out_buf;
+ char *passt_out_buf_write_ptr;
+};
+
#endif // QCOM_AUDIO_PLATFORM_H