author | Lawrence Mok <lawrence.mok@amlogic.com> | 2016-04-23 00:48:42 (GMT) |
---|---|---|
committer | Lawrence Mok <lawrence.mok@amlogic.com> | 2016-04-23 00:48:42 (GMT) |
commit | 73525014e852b2444ec3a997f1eb92a43514e424 (patch) | |
tree | 43fff0a8620e183fa1927b8697cf2171837c3024 | |
parent | a0e1371f08b43a99f74a6f87316d7a14d4251cf2 (diff) | |
download | audio-73525014e852b2444ec3a997f1eb92a43514e424.zip audio-73525014e852b2444ec3a997f1eb92a43514e424.tar.gz audio-73525014e852b2444ec3a997f1eb92a43514e424.tar.bz2 |
squash merge l-amlogic
Conflicts:
libTVaudio/audio/audio_amaudio.cpp
libTVaudio/audio_amaudio.h
Change-Id: I4a441bf66d634315d2f695283f9473bd53df3bdd
-rw-r--r-- | Android.mk | 7 | ||||
-rw-r--r-- | audio_hw.c | 633 | ||||
-rw-r--r-- | hdmi_audio_hw.c | 21 | ||||
-rw-r--r-- | libTVaudio/Android.mk | 13 | ||||
-rw-r--r-- | libTVaudio/audio/DDP_media_source.cpp | 164 | ||||
-rw-r--r-- | libTVaudio/audio/amaudio_main.cpp | 23 | ||||
-rw-r--r-- | libTVaudio/audio/aml_audio.c | 674 | ||||
-rw-r--r-- | libTVaudio/audio/aml_audio.h | 15 | ||||
-rw-r--r-- | libTVaudio/audio/android_out.cpp | 217 | ||||
-rw-r--r-- | libTVaudio/audio/android_out.h | 2 | ||||
-rw-r--r-- | libTVaudio/audio/audio_amaudio.cpp | 177 | ||||
-rw-r--r-- | libTVaudio/audio/audio_effect_control.c | 33 | ||||
-rw-r--r-- | libTVaudio/audio/audio_effect_control.h | 1 | ||||
-rw-r--r-- | libTVaudio/audio/audio_usb_check.cpp | 134 | ||||
-rw-r--r-- | libTVaudio/audio/audio_usb_check.h | 12 | ||||
-rw-r--r-- | libTVaudio/audio_amaudio.h | 15 |
16 files changed, 1391 insertions, 750 deletions
@@ -27,12 +27,15 @@ ifeq ($(strip $(BOARD_ALSA_AUDIO)),tiny) LOCAL_MODULE := audio.primary.amlogic LOCAL_MODULE_RELATIVE_PATH := hw LOCAL_SRC_FILES := \ - audio_hw.c + audio_hw.c \ + libTVaudio/audio/audio_effect_control.c LOCAL_C_INCLUDES += \ external/tinyalsa/include \ system/media/audio_utils/include \ system/media/audio_effects/include \ - system/media/audio_route/include + system/media/audio_route/include \ + libTVaudio/audio + LOCAL_SHARED_LIBRARIES := \ liblog libcutils libtinyalsa \ libaudioutils libdl libaudioroute libutils @@ -30,28 +30,29 @@ #include <stdlib.h> #include <sys/stat.h> #include <fcntl.h> - +#include <time.h> +#include <utils/Timers.h> #include <cutils/log.h> #include <cutils/str_parms.h> #include <cutils/properties.h> - +#include <linux/ioctl.h> #include <hardware/hardware.h> #include <system/audio.h> #include <hardware/audio.h> - +#include <sound/asound.h> #include <tinyalsa/asoundlib.h> #include <audio_utils/resampler.h> #include <audio_utils/echo_reference.h> #include <hardware/audio_effect.h> #include <audio_effects/effect_aec.h> #include <audio_route/audio_route.h> -#include <time.h> -#include <utils/Timers.h> + +#include "libTVaudio/audio/audio_effect_control.h" /* ALSA cards for AML */ -#define CARD_AMLOGIC_BOARD 0 +#define CARD_AMLOGIC_BOARD 0 #define CARD_AMLOGIC_USB 1 -#define CARD_AMLOGIC_DEFAULT CARD_AMLOGIC_BOARD +#define CARD_AMLOGIC_DEFAULT CARD_AMLOGIC_BOARD /* ALSA ports for AML */ #define PORT_MM 0 /* number of frames per period */ @@ -137,6 +138,11 @@ struct aml_stream_out { bool low_power; uint32_t frame_count; int fram_write_sum; + int32_t *tmp_buffer_8ch; + int is_tv_platform; + void *audioeffect_tmp_buffer; + int has_SRS_lib; + int has_EQ_lib; }; #define MAX_PREPROCESSORS 3 /* maximum one AGC + one NS + one AEC per input stream */ @@ -164,7 +170,7 @@ struct aml_stream_in { size_t ref_buf_size; size_t ref_frames_in; int read_status; - + struct aml_audio_device *dev; }; @@ -205,6 +211,24 @@ static int get_sysfs_int(const char * path) } return val; } + +static int set_sysfs_type(const char *path, const char *type) +{ + int ret = -1; + int fd = open(path, O_CREAT | O_RDWR | O_TRUNC, 0644); + if (fd >= 0) { + char set_type[10] = {0}; + int length = snprintf(set_type, sizeof(set_type), "%s", type); + if (length > 0) + ret = write(fd, set_type, length); + LOGFUNC("%s , %s\n", path, set_type); + close(fd); + }else{ + LOGFUNC("open hdmi-tx node:%s failed!\n", path); + } + return ret; +} + static void select_devices(struct aml_audio_device *adev) { LOGFUNC("%s(mode=%d, out_device=%#x)", __FUNCTION__, adev->mode, adev->out_device); @@ -223,11 +247,14 @@ static void select_devices(struct aml_audio_device *adev) earpiece = adev->out_device & AUDIO_DEVICE_OUT_EARPIECE; mic_in = adev->in_device & ( AUDIO_DEVICE_IN_BUILTIN_MIC | AUDIO_DEVICE_IN_BACK_MIC); headset_mic = adev->in_device & AUDIO_DEVICE_IN_WIRED_HEADSET; - - LOGFUNC("~~~~ %s : hs=%d , hp=%d, sp=%d, hdmi=0x%x,earpiece=0x%x", __func__, headset_on, headphone_on, speaker_on,hdmi_on,earpiece); - LOGFUNC("~~~~ %s : in_device(%#x), mic_in(%#x), headset_mic(%#x)", __func__, adev->in_device, mic_in, headset_mic); + + LOGFUNC("%s : hs=%d , hp=%d, sp=%d, hdmi=0x%x,earpiece=0x%x", __func__, + headset_on, headphone_on, speaker_on,hdmi_on,earpiece); + LOGFUNC("%s : in_device(%#x), mic_in(%#x), headset_mic(%#x)", __func__, + adev->in_device, mic_in, headset_mic); audio_route_reset(adev->ar); - LOGFUNC("****%s : output_standby=%d,input_standby=%d",__func__,output_standby,input_standby); + LOGFUNC("%s : output_standby=%d,input_standby=%d", __func__, + output_standby, input_standby); if (hdmi_on) audio_route_apply_path(adev->ar, "hdmi"); if (headphone_on || headset_on) @@ -238,58 +265,11 @@ static void select_devices(struct aml_audio_device *adev) audio_route_apply_path(adev->ar, "main_mic"); if (headset_mic) audio_route_apply_path(adev->ar, "headset-mic"); - - audio_route_update_mixer(adev->ar); -} - -#if 0 -static void select_output_device(struct aml_audio_device *adev) -{ - LOGFUNC("%s(mode=%d, out_device=%#x)", __FUNCTION__, adev->mode, adev->out_device); - int headset_on; - int headphone_on; - int speaker_on; - int hdmi_on; - int earpiece; - //adev->cur_devices = adev->devices; + audio_route_update_mixer(adev->ar); - headset_on = adev->out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET; - headphone_on = adev->out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE; - speaker_on = adev->out_device & AUDIO_DEVICE_OUT_SPEAKER; - hdmi_on = adev->out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL; - earpiece = adev->out_device & AUDIO_DEVICE_OUT_EARPIECE; - LOGFUNC("~~~~ %s : hs=%d , hp=%d, sp=%d, hdmi=0x%x,earpiece=0x%x", __func__, headset_on, headphone_on, speaker_on,hdmi_on,earpiece); - reset_mixer_state(adev->ar); - - if (hdmi_on) - audio_route_apply_path(adev->ar, "hdmi"); - if (headphone_on || headset_on) - audio_route_apply_path(adev->ar, "headphone"); - if (speaker_on ||earpiece ) - audio_route_apply_path(adev->ar, "speaker"); - update_mixer_state(adev->ar); } -static void select_input_device(struct aml_audio_device *adev) -{ - int mic_in = adev->in_device & ( AUDIO_DEVICE_IN_BUILTIN_MIC | AUDIO_DEVICE_IN_BACK_MIC); - int headset_mic = adev->in_device & AUDIO_DEVICE_IN_WIRED_HEADSET; - LOGFUNC("~~~~ %s : in_device(%#x), mic_in(%#x), headset_mic(%#x)", __func__, adev->in_device, mic_in, headset_mic); - - //reset_mixer_state(adev->ar); - if (mic_in) - { - audio_route_apply_path(adev->ar, "main_mic"); - } - if (headset_mic) - { - audio_route_apply_path(adev->ar, "headset-mic"); - } - update_mixer_state(adev->ar); - return; -} -#endif static void force_all_standby(struct aml_audio_device *adev) { struct aml_stream_in *in; @@ -311,6 +291,7 @@ static void force_all_standby(struct aml_audio_device *adev) pthread_mutex_unlock(&in->lock); } } + static void select_mode(struct aml_audio_device *adev) { LOGFUNC("%s(out_device=%#x)", __FUNCTION__, adev->out_device); @@ -331,57 +312,12 @@ static void select_mode(struct aml_audio_device *adev) adev->in_device = AUDIO_DEVICE_IN_BUILTIN_MIC & ~AUDIO_DEVICE_BIT_IN; else adev->out_device &= ~AUDIO_DEVICE_OUT_SPEAKER; - - return; -} -#if 0 -/* - type : 0 -> playback, 1 -> capture -*/ -#define MAX_CARD_NUM 2 -int get_external_card(int type) -{ - int card_num = 1; // start num, 0 is defualt sound card. - - struct stat card_stat; - char fpath[256]; - int ret; - - - while(card_num <= MAX_CARD_NUM) - { - snprintf(fpath, sizeof(fpath), "/proc/asound/card%d", card_num); - - ret = stat(fpath, &card_stat); - //ALOGV("stat : %s : %d\n", fpath, ret); - - if(ret < 0) - { - ret = -1; - } - else - { - snprintf(fpath, sizeof(fpath), "/dev/snd/pcmC%uD0%c", card_num, - type ? 'c' : 'p'); - - ret = stat(fpath, &card_stat); - //ALOGV("stat : %s : %d\n", fpath, ret); - - if(ret == 0) - { - return card_num; - } - - } - card_num++; - } - - return ret; + return; } -#endif -static int get_aml_card(){ +static int get_aml_card(void) +{ int card = -1, err = 0; int fd = -1; unsigned fileSize = 512; @@ -416,7 +352,8 @@ OUT: return card; } -static int get_pcm_bt_port(){ +static int get_pcm_bt_port(void) +{ int port = -1, err = 0; int fd = -1; unsigned fileSize = 512; @@ -493,7 +430,8 @@ static int start_output_stream(struct aml_stream_out *out) unsigned int port = PORT_MM; int ret; - LOGFUNC("%s(adev->out_device=%#x, adev->mode=%d)", __FUNCTION__, adev->out_device, adev->mode); + LOGFUNC("%s(adev->out_device=%#x, adev->mode=%d)", + __FUNCTION__, adev->out_device, adev->mode); adev->active_output = out; @@ -501,7 +439,7 @@ static int start_output_stream(struct aml_stream_out *out) /* FIXME: only works if only one output can be active at a time */ select_devices(adev); } - + card = get_aml_card(); if (adev->out_device & AUDIO_DEVICE_OUT_ALL_SCO){ port = get_pcm_bt_port(); @@ -510,13 +448,7 @@ static int start_output_stream(struct aml_stream_out *out) port = PORT_MM; out->config = pcm_config_out; } - LOGFUNC("*%s, open card(%d) port(%d)-------", __FUNCTION__,card,port); - //if(getprop_bool("media.libplayer.wfd")){ - // out->config.period_size = PERIOD_SIZE/2; - //} - //else{ - out->config.period_size = PERIOD_SIZE; - //} + LOGFUNC("*%s, open card(%d) port(%d)", __FUNCTION__,card,port); /* default to low power: will be corrected in out_write if necessary before first write to * tinyalsa. @@ -524,7 +456,7 @@ static int start_output_stream(struct aml_stream_out *out) out->write_threshold = out->config.period_size*PLAYBACK_PERIOD_COUNT; out->config.start_threshold = out->config.period_size * PLAYBACK_PERIOD_COUNT; out->config.avail_min = 0;//SHORT_PERIOD_SIZE; - + out->frame_count = 0; out->pcm = pcm_open(card, port, PCM_OUT /*| PCM_MMAP | PCM_NOIRQ*/, &(out->config)); if (!pcm_is_ready(out->pcm)) { @@ -548,7 +480,7 @@ static int start_output_stream(struct aml_stream_out *out) ALOGE("cannot create resampler for output"); return -ENOMEM; } - out->buffer_frames = (pcm_config_out.period_size * out->config.rate) / + out->buffer_frames = (out->config.period_size * out->config.rate) / out_get_sample_rate(&out->stream.common) + 1; out->buffer = malloc(pcm_frames_to_bytes(out->pcm, out->buffer_frames)); if (out->buffer == NULL){ @@ -567,6 +499,10 @@ static int start_output_stream(struct aml_stream_out *out) out->resampler->reset(out->resampler); } + if (out->is_tv_platform == 1) { + set_sysfs_type("/sys/class/amhdmitx/amhdmitx0/aud_output_chs", "2:1"); + } + return 0; } @@ -649,7 +585,7 @@ static void put_echo_reference(struct aml_audio_device *adev, } static struct echo_reference_itfe *get_echo_reference(struct aml_audio_device *adev, - audio_format_t format, + audio_format_t format __unused, uint32_t channel_count, uint32_t sampling_rate) { @@ -697,13 +633,12 @@ static int get_playback_delay(struct aml_stream_out *out, DEFAULT_OUT_SAMPLING_RATE); ALOGV("get_playback_delay time_stamp = [%ld].[%ld], delay_ns: [%d]," - "kernel_frames:[%d]", - buffer->time_stamp.tv_sec , buffer->time_stamp.tv_nsec, buffer->delay_ns, - kernel_frames); + "kernel_frames:[%d]", buffer->time_stamp.tv_sec , buffer->time_stamp.tv_nsec, + buffer->delay_ns, kernel_frames); return 0; } -static uint32_t out_get_sample_rate(const struct audio_stream *stream) +static uint32_t out_get_sample_rate(const struct audio_stream *stream __unused) { //struct aml_stream_out *out = (struct aml_stream_out *)stream; //LOGFUNC("%s(%p)", __FUNCTION__, stream); @@ -711,7 +646,7 @@ static uint32_t out_get_sample_rate(const struct audio_stream *stream) return DEFAULT_OUT_SAMPLING_RATE; } -static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate) +static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused) { return 0; } @@ -723,25 +658,25 @@ static size_t out_get_buffer_size(const struct audio_stream *stream) //LOGFUNC("%s(out->config.rate=%d)", __FUNCTION__, out->config.rate); /* take resampling into account and return the closest majoring - * multiple of 16 frames, as audioflinger expects audio buffers to - * be a multiple of 16 frames - */ + * multiple of 16 frames, as audioflinger expects audio buffers to + * be a multiple of 16 frames + */ size_t size = (out->config.period_size * DEFAULT_OUT_SAMPLING_RATE) / out->config.rate; size = ((size + 15) / 16) * 16; return size * audio_stream_out_frame_size((struct audio_stream_out *)stream); } -static audio_channel_mask_t out_get_channels(const struct audio_stream *stream) +static audio_channel_mask_t out_get_channels(const struct audio_stream *stream __unused) { return AUDIO_CHANNEL_OUT_STEREO; } -static audio_format_t out_get_format(const struct audio_stream *stream) +static audio_format_t out_get_format(const struct audio_stream *stream __unused) { return AUDIO_FORMAT_PCM_16_BIT; } -static int out_set_format(struct audio_stream *stream, audio_format_t format) +static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused) { return 0; } @@ -767,15 +702,16 @@ static int do_output_standby(struct aml_stream_out *out) release_resampler(out->resampler); out->resampler = NULL; } +#if 0 /* if in call, don't turn off the output stage. This will be done when the call is ended */ + if (adev->mode != AUDIO_MODE_IN_CALL) { /* FIXME: only works if only one output can be active at a time */ - - // reset_mixer_state(adev->ar); - // update_mixer_state(adev->ar); + reset_mixer_state(adev->ar); + update_mixer_state(adev->ar); } - +#endif /* stop writing to echo reference */ if (out->echo_reference != NULL) { out->echo_reference->write(out->echo_reference, NULL); @@ -784,11 +720,14 @@ static int do_output_standby(struct aml_stream_out *out) out->standby = 1; output_standby = 1; - LOGFUNC("%s : output_standby=%d,input_standby=%d", __FUNCTION__, output_standby,input_standby); +#if 0 + LOGFUNC("%s : output_standby=%d,input_standby=%d", + __FUNCTION__, output_standby,input_standby); if(output_standby && input_standby){ - // reset_mixer_state(adev->ar); - // update_mixer_state(adev->ar); + reset_mixer_state(adev->ar); + update_mixer_state(adev->ar); } +#endif } return 0; } @@ -806,7 +745,7 @@ static int out_standby(struct audio_stream *stream) return status; } -static int out_dump(const struct audio_stream *stream, int fd) +static int out_dump(const struct audio_stream *stream __unused, int fd __unused) { LOGFUNC("%s(%p, %d)", __FUNCTION__, stream, fd); return 0; @@ -834,6 +773,7 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) pthread_mutex_lock(&out->lock); if (((adev->out_device & AUDIO_DEVICE_OUT_ALL) != val) && (val != 0)) { if (out == adev->active_output) { + ALOGI("audio hw select device!\n"); do_output_standby(out); /* a change in output device may change the microphone selection */ if (adev->active_input && @@ -859,93 +799,160 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) pthread_mutex_unlock(&in->lock); } pthread_mutex_unlock(&adev->lock); - goto exit; + goto exit; } - int sr = 0; + int sr = 0; ret = str_parms_get_int(parms, AUDIO_PARAMETER_STREAM_SAMPLING_RATE, &sr); if (ret >= 0) { - if(sr > 0){ + if (sr > 0) { ALOGI("audio hw sampling_rate change from %d to %d \n",DEFAULT_OUT_SAMPLING_RATE,sr); DEFAULT_OUT_SAMPLING_RATE = sr; pcm_config_out.rate = DEFAULT_OUT_SAMPLING_RATE; out->config.rate = DEFAULT_OUT_SAMPLING_RATE; - pthread_mutex_lock(&adev->lock); - pthread_mutex_lock(&out->lock); - if(!out->standby && (out == adev->active_output)){ + pthread_mutex_lock(&adev->lock); + pthread_mutex_lock(&out->lock); + if (!out->standby && (out == adev->active_output)) { do_output_standby(out); start_output_stream(out); out->standby = 0; output_standby = 0; } pthread_mutex_unlock(&adev->lock); - pthread_mutex_unlock(&out->lock); - + pthread_mutex_unlock(&out->lock); } - goto exit; + goto exit; } - int frame_size = 0; + int frame_size = 0; ret = str_parms_get_int(parms, AUDIO_PARAMETER_STREAM_FRAME_COUNT, &frame_size); if (ret >= 0) { - if(frame_size > 0){ + if (frame_size > 0) { ALOGI("audio hw frame size change from %d to %d \n",PERIOD_SIZE,frame_size); - PERIOD_SIZE = frame_size;///PLAYBACK_PERIOD_COUNT; + PERIOD_SIZE = frame_size; pcm_config_out.period_size = PERIOD_SIZE; out->config.period_size = PERIOD_SIZE; pthread_mutex_lock(&adev->lock); - pthread_mutex_lock(&out->lock); - if(!out->standby && (out == adev->active_output)){ + pthread_mutex_lock(&out->lock); + if (!out->standby && (out == adev->active_output)) { do_output_standby(out); start_output_stream(out); out->standby = 0; output_standby = 0; } pthread_mutex_unlock(&adev->lock); - pthread_mutex_unlock(&out->lock); - + pthread_mutex_unlock(&out->lock); } - } -exit: + goto exit; + } + int EQ_parameters[5] = {0, 0, 0, 0, 0}; + char tmp[2]; + int data = 0, i = 0; + ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_EQ, value, sizeof(value)); + //ALOGI("audio effect EQ parameters are %s\n", value); + if (ret >= 0) { + for (i; i < 5; i++) { + tmp[0] = value[2*i]; + tmp[1] = value[2*i + 1]; + data = atoi(tmp); + EQ_parameters[i] = data -10; + } + ALOGI("audio effect EQ parameters are %d,%d,%d,%d,%d\n", EQ_parameters[0], + EQ_parameters[1], EQ_parameters[2], EQ_parameters[3], EQ_parameters[4]); + ret = 0; + HPEQ_setParameter(EQ_parameters[0], EQ_parameters[1], + EQ_parameters[2], EQ_parameters[3], EQ_parameters[4]); + goto exit; + } + int SRS_parameters[5] = {0, 0, 0, 0, 0}; + char tmp1[3]; + ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_SRS, value, sizeof(value)); + //ALOGI("audio effect SRS parameters are %s\n", value); + if (ret >= 0) { + for (i; i < 5; i++) { + tmp1[0] = value[3*i]; + tmp1[1] = value[3*i + 1]; + tmp1[2] = value[3*i + 2]; + SRS_parameters[i] = atoi(tmp1); + } + ALOGI("audio effect SRS parameters are %d,%d,%d,%d,%d\n", SRS_parameters[0], + SRS_parameters[1], SRS_parameters[2], SRS_parameters[3], SRS_parameters[4]); + ret = 0; + srs_setParameter(SRS_parameters); + goto exit; + } + int SRS_gain[2] = {0, 0}; + ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_SRS_GAIN, value, sizeof(value)); + if (ret >= 0) { + for (i; i < 2; i++) { + tmp1[0] = value[3*i]; + tmp1[1] = value[3*i + 1]; + tmp1[2] = value[3*i + 2]; + SRS_gain[i] = atoi(tmp1); + } + ALOGI("audio effect SRS input/output gain are %d,%d\n", SRS_gain[0], SRS_gain[1]); + ret = 0; + srs_set_gain(SRS_gain[0], SRS_gain[1]); + goto exit; + } + int SRS_switch[3] = {0, 0, 0}; + ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_SRS_SWITCH, value, sizeof(value)); + if (ret >= 0) { + for (i; i < 3; i++) { + tmp[0] = value[2*i]; + tmp[1] = value[2*i + 1]; + SRS_switch[i] = atoi(tmp); + } + ALOGI("audio effect SRS switch %d, %d, %d\n", SRS_switch[0], SRS_switch[1], SRS_switch[2]); + ret = 0; + srs_surround_enable(SRS_switch[0]); + srs_dialogclarity_enable(SRS_switch[1]); + srs_truebass_enable(SRS_switch[2]); + goto exit; + } +exit: str_parms_destroy(parms); return ret; } -static char * out_get_parameters(const struct audio_stream *stream, const char *keys) +static char * out_get_parameters(const struct audio_stream *stream __unused, const char *keys __unused) { return strdup(""); } -#if 0 + static uint32_t out_get_latency(const struct audio_stream_out *stream) { - struct aml_stream_out *out = (struct aml_stream_out *)stream; - uint32_t whole_latency; - uint32_t ret; - - whole_latency = (out->config.period_size * out->config.period_count * 1000) / out->config.rate; - + struct aml_stream_out *out = (struct aml_stream_out *)stream; + uint32_t whole_latency; + uint32_t ret; + snd_pcm_sframes_t frames = 0; + whole_latency = (out->config.period_size * out->config.period_count * 1000) / out->config.rate; if (!out->pcm || !pcm_is_ready(out->pcm)) return whole_latency; - - ret = pcm_get_latency(out->pcm); - - if(ret == -1){ - return whole_latency; - } - return ret; + ret = pcm_ioctl(out->pcm,SNDRV_PCM_IOCTL_DELAY,&frames); + if (ret < 0) { + return whole_latency; + } + return (frames * 1000)/DEFAULT_OUT_SAMPLING_RATE/* (out->pcm->config.rate)*/; } -#else -static uint32_t out_get_latency(const struct audio_stream_out *stream) -{ - struct aml_stream_out *out = (struct aml_stream_out *)stream; - return (out->config.period_size * out->config.period_count * 1000) / out->config.rate; -} -#endif -static int out_set_volume(struct audio_stream_out *stream, float left, - float right) +static int out_set_volume(struct audio_stream_out *stream __unused, float left __unused, float right __unused) { return -ENOSYS; } +static int audio_effect_process(struct audio_stream_out *stream, + short* buffer, int frame_size) +{ + struct aml_stream_out *out = (struct aml_stream_out *)stream; + int output_size = frame_size << 2; + if (out->has_SRS_lib) { + output_size = srs_process(buffer, buffer, frame_size); + } + if (out->has_EQ_lib) { + HPEQ_process(buffer, buffer, frame_size); + } + return output_size; +} + static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, size_t bytes) { @@ -973,29 +980,7 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, */ pthread_mutex_lock(&adev->lock); pthread_mutex_lock(&out->lock); - #if 0 - #define DOLBY_SYSTEM_CHANNEL "ds1.audio.multichannel.support" - char value[128]={0}; - property_get(DOLBY_SYSTEM_CHANNEL,value,NULL); - if((!strcmp(value,"true") ||!strcmp(value,"1")) && out->config.channels!=8) - { - if (!out->standby) { - ALOGI("[%s %d]8ch PCM output,standby other outputs/%p...\n",__FUNCTION__,__LINE__,out); - pcm_close(out->pcm); - out->pcm = NULL; - out->frame_count = 0; - adev->active_output = 0; - if (out->echo_reference != NULL) {/* stop writing to echo reference */ - out->echo_reference->write(out->echo_reference, NULL); - out->echo_reference = NULL; - } - out->standby = 1; - output_standby = 1; - } - pthread_mutex_unlock(&adev->lock); - goto exit; - } - #endif + if (out->standby) { ret = start_output_stream(out); if (ret != 0) { @@ -1043,72 +1028,57 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, out->echo_reference->write(out->echo_reference, &b); } -#if 0 - FILE *fp1=fopen("/data/audio_out","a+"); - if(fp1){ - int flen=fwrite((char *)in_buffer,1,out_frames * frame_size,fp1); - LOGFUNC("flen = %d---outlen=%d ", flen, out_frames * frame_size); - fclose(fp1); - }else{ - LOGFUNC("could not open file:audio_out"); +#if 1 + if (getprop_bool("media.audiohal.outdump")) { + FILE *fp1=fopen("/data/i2s_audio_out.pcm","a+"); + if (fp1) { + int flen=fwrite((char *)in_buffer,1,out_frames * frame_size,fp1); + LOGFUNC("flen = %d---outlen=%d ", flen, out_frames * frame_size); + fclose(fp1); + } else { + LOGFUNC("could not open file:/data/i2s_audio_out.pcm"); } + } #endif -#if 0 - if(out->config.rate != DEFAULT_OUT_SAMPLING_RATE) { - total_len = out_frames*frame_size + cached_len; - - - LOGFUNC("total_len(%d) = resampler_out_len(%d) + cached_len111(%d)", total_len, out_frames*frame_size, cached_len); - - data_src = (char *)cache_buffer_bytes; - data_dst = (char *)output_buffer_bytes; - - - /*write_back data from cached_buffer*/ - if(cached_len){ - memcpy((void *)data_dst, (void *)data_src, cached_len); - data_dst += cached_len; - } - - ouput_len = total_len &(~0x3f); - data = (char*)in_buffer; - - memcpy((void *)data_dst, (void *)data, ouput_len-cached_len); - data += (ouput_len-cached_len); - cached_len = total_len & 0x3f; - data_src = (char *)cache_buffer_bytes; - - /*save data to cached_buffer*/ - if(cached_len){ - memcpy((void *)data_src, (void *)data, cached_len); - } - - ret = pcm_write(out->pcm, (void *)output_buffer_bytes, ouput_len); - - }else{ - ret = pcm_write(out->pcm, in_buffer, out_frames * frame_size); - } -#else codec_type = get_sysfs_int("/sys/class/audiodsp/digital_codec"); samesource_flag = get_sysfs_int("/sys/class/audiodsp/audio_samesource"); - if (samesource_flag == 0 && codec_type == 0) { + if (samesource_flag == 0 && codec_type == 0) { ALOGI("to enable same source,need reset alsa,type %d,same source flag %d \n",codec_type,samesource_flag); pcm_stop(out->pcm); } - ret = pcm_write(out->pcm, in_buffer, out_frames * frame_size); + + if (out->is_tv_platform == 1) { + int16_t *tmp_buffer = (int16_t *)out->audioeffect_tmp_buffer; + memcpy((void *)tmp_buffer, (void *)in_buffer, out_frames*4); + audio_effect_process(stream, tmp_buffer, out_frames); + for (i = 0; i < out_frames; i ++) { + out->tmp_buffer_8ch[8*i] = ((int32_t)(in_buffer[2*i])) << 16; + out->tmp_buffer_8ch[8*i + 1] = ((int32_t)(in_buffer[2*i + 1])) << 16; + out->tmp_buffer_8ch[8*i + 2] = ((int32_t)(tmp_buffer[2*i])) << 16; + out->tmp_buffer_8ch[8*i + 3] = ((int32_t)(tmp_buffer[2*i + 1])) << 16; + out->tmp_buffer_8ch[8*i + 4] = 0; + out->tmp_buffer_8ch[8*i + 5] = 0; + out->tmp_buffer_8ch[8*i + 6] = 0; + out->tmp_buffer_8ch[8*i + 7] = 0; + } + /*if (out->frame_count < 5*1024) { + memset(out->tmp_buffer_8ch, 0, out_frames * frame_size * 8); + }*/ + ret = pcm_write(out->pcm, out->tmp_buffer_8ch, out_frames * frame_size * 8); + } else { + ret = pcm_write(out->pcm, in_buffer, out_frames * frame_size); + } out->frame_count += out_frames; out->fram_write_sum+=out_frames; -#endif + exit: pthread_mutex_unlock(&out->lock); - //fixed me: It is not a good way to clear android audioflinger buffer,but when pcm write error, audioflinger can't break out. - memset(in_buffer,0,bytes); if (ret != 0) { usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) / out_get_sample_rate(&stream->common)); } - + if (force_input_standby) { pthread_mutex_lock(&adev->lock); if (adev->active_input) { @@ -1128,21 +1098,21 @@ static int out_get_render_position(const struct audio_stream_out *stream, struct aml_stream_out *out = (struct aml_stream_out *)stream; *dsp_frames = out->frame_count; - + return 0; } -static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect) +static int out_add_audio_effect(const struct audio_stream *stream __unused, effect_handle_t effect __unused) { return 0; } -static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect) +static int out_remove_audio_effect(const struct audio_stream *stream __unused, effect_handle_t effect __unused) { return 0; } -static int out_get_next_write_timestamp(const struct audio_stream_out *stream, - int64_t *timestamp) +static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused, + int64_t *timestamp __unused) { return -EINVAL; } @@ -1160,7 +1130,7 @@ static int out_get_presentation_position(const struct audio_stream_out *stream,u return 0; } -static int get_next_buffer(struct resampler_buffer_provider *buffer_provider, +static int get_next_buffer(struct resampler_buffer_provider *buffer_provider, struct resampler_buffer* buffer); static void release_buffer(struct resampler_buffer_provider *buffer_provider, struct resampler_buffer* buffer); @@ -1239,7 +1209,7 @@ static uint32_t in_get_sample_rate(const struct audio_stream *stream) return in->requested_rate; } -static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate) +static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused) { return 0; } @@ -1264,12 +1234,12 @@ static audio_channel_mask_t in_get_channels(const struct audio_stream *stream) } } -static audio_format_t in_get_format(const struct audio_stream *stream) +static audio_format_t in_get_format(const struct audio_stream *stream __unused) { return AUDIO_FORMAT_PCM_16_BIT; } -static int in_set_format(struct audio_stream *stream, audio_format_t format) +static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused) { return 0; } @@ -1299,11 +1269,14 @@ static int do_input_standby(struct aml_stream_in *in) in->standby = 1; input_standby = true; - LOGFUNC("%s : output_standby=%d,input_standby=%d", __FUNCTION__, output_standby,input_standby); +#if 0 + LOGFUNC("%s : output_standby=%d,input_standby=%d", + __FUNCTION__, output_standby,input_standby); if(output_standby && input_standby){ - // reset_mixer_state(adev->ar); - // update_mixer_state(adev->ar); + reset_mixer_state(adev->ar); + update_mixer_state(adev->ar); } +#endif } return 0; } @@ -1321,7 +1294,7 @@ static int in_standby(struct audio_stream *stream) return status; } -static int in_dump(const struct audio_stream *stream, int fd) +static int in_dump(const struct audio_stream *stream __unused, int fd __unused) { return 0; } @@ -1365,27 +1338,28 @@ static int in_set_parameters(struct audio_stream *stream, const char *kvpairs) do_input_standby(in); pthread_mutex_unlock(&in->lock); pthread_mutex_unlock(&adev->lock); - - int framesize = 0; + + int framesize = 0; ret = str_parms_get_int(parms, AUDIO_PARAMETER_STREAM_FRAME_COUNT, &framesize); - + if (ret >= 0) { if(framesize > 0){ - ALOGI("Reset audio input hw frame size from %d to %d\n",CAPTURE_PERIOD_SIZE*CAPTURE_PERIOD_COUNT,framesize); + ALOGI("Reset audio input hw frame size from %d to %d\n", + CAPTURE_PERIOD_SIZE*CAPTURE_PERIOD_COUNT,framesize); CAPTURE_PERIOD_SIZE = framesize/CAPTURE_PERIOD_COUNT; pcm_config_in.period_size = CAPTURE_PERIOD_SIZE; in->config.period_size = CAPTURE_PERIOD_SIZE; - + pthread_mutex_lock(&adev->lock); pthread_mutex_lock(&in->lock); - + if(!in->standby && (in == adev->active_input)){ do_input_standby(in); start_input_stream(in); in->standby = 0; input_standby = false; } - + pthread_mutex_unlock(&in->lock); pthread_mutex_unlock(&adev->lock); } @@ -1395,19 +1369,19 @@ static int in_set_parameters(struct audio_stream *stream, const char *kvpairs) return ret; } -static char * in_get_parameters(const struct audio_stream *stream, - const char *keys) +static char * in_get_parameters(const struct audio_stream *stream __unused, + const char *keys __unused) { return strdup(""); } -static int in_set_gain(struct audio_stream_in *stream, float gain) +static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused) { return 0; } static void get_capture_delay(struct aml_stream_in *in, - size_t frames, + size_t frames __unused, struct echo_reference_buffer *buffer) { /* read frames available in kernel driver buffer */ @@ -1443,12 +1417,12 @@ static void get_capture_delay(struct aml_stream_in *in, buffer->time_stamp = tstamp; buffer->delay_ns = delay_ns; - ALOGV("get_capture_delay time_stamp = [%ld].[%ld], delay_ns: [%d]," + /*ALOGV("get_capture_delay time_stamp = [%ld].[%ld], delay_ns: [%d]," " kernel_delay:[%ld], buf_delay:[%ld], rsmp_delay:[%ld], kernel_frames:[%d], " "in->frames_in:[%d], in->proc_frames_in:[%d], frames:[%d]", buffer->time_stamp.tv_sec , buffer->time_stamp.tv_nsec, buffer->delay_ns, kernel_delay, buf_delay, rsmp_delay, kernel_frames, - in->frames_in, in->proc_frames_in, frames); + in->frames_in, in->proc_frames_in, frames);*/ } @@ -1458,14 +1432,12 @@ static int32_t update_echo_reference(struct aml_stream_in *in, size_t frames) b.delay_ns = 0; ALOGV("update_echo_reference, frames = [%d], in->ref_frames_in = [%d], " - "b.frame_count = [%d]", - frames, in->ref_frames_in, frames - in->ref_frames_in); + "b.frame_count = [%d]", frames, in->ref_frames_in, frames - in->ref_frames_in); if (in->ref_frames_in < frames) { if (in->ref_buf_size < frames) { in->ref_buf_size = frames; in->ref_buf = (int16_t *)realloc(in->ref_buf, - in->ref_buf_size * - in->config.channels * sizeof(int16_t)); + in->ref_buf_size * in->config.channels * sizeof(int16_t)); } b.frame_count = frames - in->ref_frames_in; @@ -1478,7 +1450,7 @@ static int32_t update_echo_reference(struct aml_stream_in *in, size_t frames) { in->ref_frames_in += b.frame_count; ALOGV("update_echo_reference: in->ref_frames_in:[%d], " - "in->ref_buf_size:[%d], frames:[%d], b.frame_count:[%d]", + "in->ref_buf_size:[%d], frames:[%d], b.frame_count:[%d]", in->ref_frames_in, in->ref_buf_size, frames, b.frame_count); } } else @@ -1570,10 +1542,8 @@ static int get_next_buffer(struct resampler_buffer_provider *buffer_provider, } if (in->frames_in == 0) { - in->read_status = pcm_read(in->pcm, - (void*)in->buffer, - in->config.period_size * - audio_stream_in_frame_size(&in->stream)); + in->read_status = pcm_read(in->pcm, (void*)in->buffer, + in->config.period_size * audio_stream_in_frame_size(&in->stream)); if (in->read_status != 0) { ALOGE("get_next_buffer() pcm_read error %d", in->read_status); buffer->raw = NULL; @@ -1770,13 +1740,13 @@ static ssize_t in_read(struct audio_stream_in *stream, void* buffer, if (ret < 0) usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) / in_get_sample_rate(&stream->common)); - + pthread_mutex_unlock(&in->lock); return bytes; } -static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream) +static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused) { return 0; } @@ -1862,9 +1832,9 @@ exit: } static int adev_open_output_stream(struct audio_hw_device *dev, - audio_io_handle_t handle, - audio_devices_t devices, - audio_output_flags_t flags, + audio_io_handle_t handle __unused, + audio_devices_t devices __unused, + audio_output_flags_t flags __unused, struct audio_config *config, struct audio_stream_out **stream_out) { @@ -1899,7 +1869,7 @@ static int adev_open_output_stream(struct audio_hw_device *dev, out->stream.get_next_write_timestamp = out_get_next_write_timestamp; out->stream.get_presentation_position=out_get_presentation_position; out->config = pcm_config_out; - + out->is_tv_platform = 0; out->dev = ladev; out->standby = true; output_standby = true; @@ -1921,6 +1891,47 @@ static int adev_open_output_stream(struct audio_hw_device *dev, config->format, config->channel_mask, config->sample_rate); *stream_out = &out->stream; + + if (getprop_bool("ro.platform.has.tvuimode")) { + pcm_config_out.channels = 8; + pcm_config_out.format = PCM_FORMAT_S32_LE; + out->is_tv_platform = 1; + out->tmp_buffer_8ch = malloc(pcm_config_out.period_size * 4 * 8); + if (out->tmp_buffer_8ch == NULL) { + ALOGE("cannot malloc memory for out->tmp_buffer_8ch"); + return -ENOMEM; + } + out->audioeffect_tmp_buffer = malloc(pcm_config_out.period_size * 6); + if (out->audioeffect_tmp_buffer == NULL) { + ALOGE("cannot malloc memory for audioeffect_tmp_buffer"); + return -ENOMEM; + } + //EQ lib load and init EQ + ret = load_EQ_lib(); + if (ret < 0) { + ALOGE("%s, Load EQ lib fail!\n", __FUNCTION__); + out->has_EQ_lib = 0; + } else { + ret = HPEQ_init(); + if (ret < 0) + out->has_EQ_lib = 0; + else + out->has_EQ_lib = 1; + HPEQ_enable(1); + } + //load srs lib and init it. + ret = load_SRS_lib(); + if (ret < 0) { + ALOGE("%s, Load SRS lib fail!\n", __FUNCTION__); + out->has_SRS_lib = 0; + } else { + ret = srs_init(48000); + if (ret < 0) + out->has_SRS_lib = 0; + else + out->has_SRS_lib = 1; + } + } return 0; err_open: @@ -1935,6 +1946,10 @@ static void adev_close_output_stream(struct audio_hw_device *dev, struct aml_stream_out *out = (struct aml_stream_out *)stream; LOGFUNC("%s(%p, %p)", __FUNCTION__, dev, stream); + if (out->is_tv_platform == 1) { + free(out->tmp_buffer_8ch); + free(out->audioeffect_tmp_buffer); + } out_standby(&stream->common); free(stream); } @@ -1942,7 +1957,7 @@ static void adev_close_output_stream(struct audio_hw_device *dev, static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) { LOGFUNC("%s(%p, %s)", __FUNCTION__, dev, kvpairs); - + struct aml_audio_device *adev = (struct aml_audio_device *)dev; struct str_parms *parms; char *str; @@ -1962,39 +1977,39 @@ static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) return ret; } -static char * adev_get_parameters(const struct audio_hw_device *dev, - const char *keys) +static char * adev_get_parameters(const struct audio_hw_device *dev __unused, + const char *keys __unused) { return strdup(""); } -static int adev_init_check(const struct audio_hw_device *dev) +static int adev_init_check(const struct audio_hw_device *dev __unused) { return 0; } -static int adev_set_voice_volume(struct audio_hw_device *dev, float volume) +static int adev_set_voice_volume(struct audio_hw_device *dev __unused, float volume __unused) { return 0; } -static int adev_set_master_volume(struct audio_hw_device *dev, float volume) +static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused) { return -ENOSYS; } -static int adev_get_master_volume(struct audio_hw_device *dev, - float *volume) +static int adev_get_master_volume(struct audio_hw_device *dev __unused, + float *volume __unused) { return -ENOSYS; } -static int adev_set_master_mute(struct audio_hw_device *dev, bool muted) +static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused) { return -ENOSYS; } -static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted) +static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused) { return -ENOSYS; } @@ -2049,7 +2064,7 @@ static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev, } static int adev_open_input_stream(struct audio_hw_device *dev, - audio_io_handle_t handle, + audio_io_handle_t handle __unused, audio_devices_t devices, struct audio_config *config, struct audio_stream_in **stream_in, @@ -2059,7 +2074,7 @@ static int adev_open_input_stream(struct audio_hw_device *dev, struct aml_stream_in *in; int ret; int channel_count = popcount(config->channel_mask); - LOGFUNC("**********%s(%#x, %d, 0x%04x, %d)", __FUNCTION__, + LOGFUNC("%s(%#x, %d, 0x%04x, %d)", __FUNCTION__, devices, config->format, config->channel_mask, config->sample_rate); if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) return -EINVAL; @@ -2168,7 +2183,7 @@ static void adev_close_input_stream(struct audio_hw_device *dev, return; } -static int adev_dump(const audio_hw_device_t *device, int fd) +static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused) { return 0; } diff --git a/hdmi_audio_hw.c b/hdmi_audio_hw.c index dab9053..a97707f 100644 --- a/hdmi_audio_hw.c +++ b/hdmi_audio_hw.c @@ -1206,17 +1206,16 @@ out_write (struct audio_stream_out *stream, const void *buffer, size_t bytes) out->echo_reference->write (out->echo_reference, &b); } -#if 0 - FILE *fp = fopen ("/data/audio_out.pcm", "a+"); - if (fp) - { - int flen = fwrite ((char *) buffer, 1, out_frames * frame_size, fp); - LOGFUNC ("flen = %d---outlen=%d ", flen, out_frames * frame_size); - fclose (fp); - } - else - { - LOGFUNC ("could not open file:audio_out"); +#if 1 + if (getprop_bool("media.audiohal.outdump")) { + FILE *fp1=fopen("/data/hdmi_audio_out.pcm","a+"); + if (fp1) { + int flen=fwrite((char *)buffer,1,out_frames * frame_size,fp1); + LOGFUNC("flen = %d---outlen=%d ", flen, out_frames * frame_size); + fclose(fp1); + } else { + LOGFUNC("could not open file:/data/hdmi_audio_out.pcm"); + } } #endif diff --git a/libTVaudio/Android.mk b/libTVaudio/Android.mk index 91ef7dc..17b0ef5 100644 --- a/libTVaudio/Android.mk +++ b/libTVaudio/Android.mk @@ -5,9 +5,16 @@ include $(CLEAR_VARS) LOCAL_MODULE := libTVaudio LOCAL_SHARED_LIBRARIES := libcutils libutils libtinyalsa libdl \ - libmedia libbinder libusbhost libstagefright - + libmedia libbinder libstagefright +ifneq (0, $(shell expr $(PLATFORM_VERSION) \>= 5.0)) +LOCAL_SHARED_LIBRARIES += libsystemcontrolservice +else +LOCAL_SHARED_LIBRARIES += libsystemwriteservice +endif LOCAL_C_INCLUDES := \ + $(TOP)/frameworks/native/services \ + $(TOP)/frameworks/native/include \ + $(TOP)/vendor/amlogic/frameworks/services \ external/tinyalsa/include \ frameworks/av/include/media/stagefright \ frameworks/av/include/media \ @@ -24,7 +31,7 @@ LOCAL_SRC_FILES := \ audio/amaudio_main.cpp \ audio/DDP_media_source.cpp \ -LOCAL_CFLAGS := -DANDROID_PLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION) +LOCAL_CFLAGS := -DANDROID_PLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION) -DUSE_SYS_WRITE_SERVICE=1 LOCAL_MODULE_TAGS := optional LOCAL_PRELINK_MODULE := false diff --git a/libTVaudio/audio/DDP_media_source.cpp b/libTVaudio/audio/DDP_media_source.cpp index 14eb6bf..83c6516 100644 --- a/libTVaudio/audio/DDP_media_source.cpp +++ b/libTVaudio/audio/DDP_media_source.cpp @@ -5,24 +5,109 @@ #include <cutils/properties.h> #include <pthread.h> +//code here for sys write service +#ifdef USE_SYS_WRITE_SERVICE +#include <binder/Binder.h> +#include <binder/IServiceManager.h> +#include <utils/Atomic.h> +#include <utils/Log.h> +#include <utils/RefBase.h> +#include <utils/String8.h> +#include <utils/String16.h> +#include <utils/threads.h> +#include <unistd.h> +#if ANDROID_PLATFORM_SDK_VERSION >= 21 //5.0 +#include <systemcontrol/ISystemControlService.h> +#else +#include <systemwrite/ISystemWriteService.h> +#endif +// code end +#endif + #include "DDP_media_source.h" #include "aml_audio.h" - extern struct circle_buffer android_out_buffer; extern struct circle_buffer DDP_out_buffer; - +extern struct circle_buffer DD_out_buffer; +extern int spdif_audio_type; namespace android { #define LOG_TAG "DDP_Media_Source" -static DDPerr ddbs_init(DDPshort * buf, DDPshort bitptr,DDP_BSTRM *p_bstrm) +#ifdef USE_SYS_WRITE_SERVICE +//code here for system write service +class DeathNotifier: public IBinder::DeathRecipient +{ + public: + DeathNotifier() { + } + + void binderDied(const wp<IBinder>& who) { + ALOGW("system_write died!"); + } +}; + + +#if ANDROID_PLATFORM_SDK_VERSION >= 21 //5.0 +//used ISystemControlService +#define SYST_SERVICES_NAME "system_control" +#else +//used amSystemWriteService +#define ISystemControlService ISystemWriteService +#define SYST_SERVICES_NAME "system_write" +#endif + +static sp<ISystemControlService> amSystemWriteService; +static sp<DeathNotifier> amDeathNotifier; +static Mutex amLock; +static Mutex amgLock; + +const sp<ISystemControlService>& getSystemWriteService() +{ + Mutex::Autolock _l(amgLock); + if (amSystemWriteService.get() == 0) { + sp<IServiceManager> sm = defaultServiceManager(); +#if 0 + sp<IBinder> binder; + do { + binder = sm->getService(String16("system_write")); + if (binder != 0) + break; + ALOGW("SystemWriteService not published, waiting..."); + usleep(500000); // 0.5 s + } while(true); + if (amDeathNotifier == NULL) { + amDeathNotifier = new DeathNotifier(); + } + binder->linkToDeath(amDeathNotifier); + amSystemWriteService = interface_cast<ISystemWriteService>(binder); +#endif + + + amSystemWriteService = interface_cast<ISystemControlService>(sm->getService(String16(SYST_SERVICES_NAME))); + + } + ALOGE_IF(amSystemWriteService==0, "no SystemWrite Service!?"); + + return amSystemWriteService; +} +void amSystemWriteSetProperty(const char* key, const char* value) +{ + const sp<ISystemControlService>& sws = getSystemWriteService(); + if (sws != 0) { + sws->setProperty(String16(key), String16(value)); + } +} +//code end for system write service +#endif +static DDPerr ddbs_init(DDPshort * buf, DDPshort bitptr, DDP_BSTRM *p_bstrm) { p_bstrm->buf = buf; p_bstrm->bitptr = bitptr; p_bstrm->data = *buf; return 0; } -static DDPerr ddbs_unprj(DDP_BSTRM *p_bstrm,DDPshort *p_data, DDPshort numbits) +static DDPerr ddbs_unprj(DDP_BSTRM *p_bstrm, DDPshort *p_data, DDPshort numbits) { DDPushort data; *p_data = (DDPshort)((p_bstrm->data << p_bstrm->bitptr) & msktab[numbits]); @@ -40,7 +125,7 @@ static DDPerr ddbs_unprj(DDP_BSTRM *p_bstrm,DDPshort *p_data, DDPshort numbi } -static int Get_DD_Parameters(void *buf, int *sample_rate, int *frame_size,int *ChNum) +static int Get_DD_Parameters(void *buf, int *sample_rate, int *frame_size, int *ChNum) { int numch=0; DDP_BSTRM bstrm={0}; @@ -419,20 +504,23 @@ status_t DDP_Media_Source::read(MediaBuffer **out, const ReadOptions *options) { //-------------------------------OMX codec------------------------------------------------ const char *MEDIA_MIMETYPE_AUDIO_AC3 = "audio/ac3"; +const char *MEDIA_MIMETYPE_AUDIO_EAC3 = "audio/eac3"; Aml_OMX_Codec::Aml_OMX_Codec(void) { - ALOGI("[Aml_OMX_Codec::%s: %d]\n", __FUNCTION__, __LINE__); + ALOGI("[Aml_OMX_Codec::%s: %d],atype %d\n", __FUNCTION__, __LINE__,spdif_audio_type); m_codec = NULL; status_t m_OMXClientConnectStatus = m_OMXClient.connect(); lock_init(); locked(); buf_decode_offset = 0; buf_decode_offset_pre = 0; - if (m_OMXClientConnectStatus != OK) { ALOGE("Err:omx client connect error\n"); } else { const char *mine_type = NULL; - mine_type = MEDIA_MIMETYPE_AUDIO_AC3; + if (spdif_audio_type == EAC3) + mine_type = MEDIA_MIMETYPE_AUDIO_EAC3; + else + mine_type = MEDIA_MIMETYPE_AUDIO_AC3; m_OMXMediaSource = new DDP_Media_Source(); sp < MetaData > metadata = m_OMXMediaSource->getFormat(); metadata->setCString(kKeyMIMEType, mine_type); @@ -617,32 +705,58 @@ int omx_codec_get_Nch() { void *decode_threadloop(void *args) { unsigned int outlen = 0; + unsigned int outlen_raw = 0; + unsigned int outlen_pcm = 0; int write_sucessed = 1; int ret = 0; - unsigned char tmp[8192]; - + char *tmp = NULL; + tmp = (char*)malloc(6144*4+6144+8); + if (tmp == NULL) { + ALOGE("malloc buffer failed\n"); + return NULL; + } ALOGI("[%s %d] enter!\n", __FUNCTION__, __LINE__); while (decode_ThreadStopFlag == 0) { if (write_sucessed == 1) { outlen = 0; - omx_codec_read(&tmp[0], &outlen, &(decode_ThreadStopFlag)); + outlen_raw = 0; + outlen_pcm = 0; + omx_codec_read((unsigned char*)tmp, &outlen, &(decode_ThreadStopFlag)); } if (decode_ThreadStopFlag == 1) { ALOGD("%s, exit threadloop! \n", __FUNCTION__); break; } - if (outlen > 0) { - ret = buffer_write(&DDP_out_buffer, (char *) (&tmp[0]), outlen); - if (ret < 0) { - write_sucessed = 0; - usleep(10 * 1000); //10ms - } else { - write_sucessed = 1; + if (outlen > 8) { + memcpy(&outlen_pcm,tmp,4); + memcpy(&outlen_raw,tmp+4+outlen_pcm,4); + if (outlen_pcm > 0) { + //ALOGI("pcm data size %d\n",outlen_pcm); + ret = buffer_write(&DDP_out_buffer, tmp+4, outlen_pcm); + if (ret < 0) { + write_sucessed = 0; + usleep(10 * 1000); //10ms + } else { + write_sucessed = 1; + } + } + if (outlen_raw > 0) { + //ALOGI("raw data size %d\n",outlen_raw); + ret = buffer_write(&DD_out_buffer, tmp+4+outlen_pcm+4, outlen_raw); + if (ret < 0) { + //write_sucessed = 0; + //ALOGI("raw data write failed\n"); + usleep(10 * 1000); //10ms + } else { + //write_sucessed = 1; + } } } } - decode_ThreadExitFlag = 0; + if (tmp) { + free(tmp); + } ALOGD("%s, exiting...\n", __FUNCTION__); return NULL; } @@ -709,6 +823,12 @@ extern "C" { int omx_codec_init(void) { int ret = 0; ALOGI("omx_codec_init!\n"); +#ifndef USE_SYS_WRITE_SERVICE + ret=property_set("media.libplayer.dtsopt0", "1"); + ALOGI("property_set<media.libplayer.dtsopt0> ret/%d\n",ret); +#else + amSystemWriteSetProperty("media.libplayer.dtsopt0", "1"); +#endif arm_omx_codec = new android::Aml_OMX_Codec(); if (arm_omx_codec == NULL) { ALOGE("Err:arm_omx_codec_init failed!\n"); @@ -733,6 +853,12 @@ int omx_codec_init(void) { void omx_codec_close(void) { int ret = 0; +#ifndef USE_SYS_WRITE_SERVICE + ret=property_set("media.libplayer.dtsopt0", "0"); + ALOGI("property_set<media.libplayer.dtsopt0> ret/%d\n",ret); +#else + amSystemWriteSetProperty("media.libplayer.dtsopt0", "0"); +#endif if (arm_omx_codec == NULL) { ALOGI( "NOTE:arm_omx_codec==NULL arm_omx_codec_close() do nothing! %s %d \n", diff --git a/libTVaudio/audio/amaudio_main.cpp b/libTVaudio/audio/amaudio_main.cpp index f236820..3636cac 100644 --- a/libTVaudio/audio/amaudio_main.cpp +++ b/libTVaudio/audio/amaudio_main.cpp @@ -9,7 +9,6 @@ #include <binder/IServiceManager.h> #include "../audio_amaudio.h" -#include "audio_usb_check.h" using namespace android; @@ -17,30 +16,22 @@ int main(int argc, char** argv) { sp < ProcessState > proc(ProcessState::self()); sp < IServiceManager > sm = defaultServiceManager(); - //test for audio volume control - amAudioSetAndroidVolumeEnable(1); - amAudioSetAndroidVolume(60, 60); - sleep(10); - //test for S805 HDMI_IN BOX amAudioOpen(48000, CC_IN_USE_SPDIF_DEVICE, CC_OUT_USE_AMAUDIO); - amAudioOpen(48000, CC_IN_USE_SPDIF_DEVICE, CC_OUT_USE_ANDROID); + //amAudioOpen(48000, CC_IN_USE_SPDIF_DEVICE, CC_OUT_USE_ANDROID); sleep(100); //test for TV amAudioOpen(48000, CC_IN_USE_I2S_DEVICE, CC_OUT_USE_AMAUDIO); - amAudioOpen(48000, CC_IN_USE_I2S_DEVICE, CC_OUT_USE_ANDROID); + //amAudioOpen(48000, CC_IN_USE_I2S_DEVICE, CC_OUT_USE_ANDROID); sleep(100); //test for data mix mode and mix volume - sleep(10); amAudioSetOutputMode(2); amAudioSetMusicGain(60); sleep(10); amAudioSetMusicGain(256); sleep(10); - amAudioSetAndroidVolumeEnable(0); - sleep(10); amAudioSetOutputMode(0); amAudioSetLeftGain(256); amAudioSetRightGain(256); @@ -55,14 +46,14 @@ int main(int argc, char** argv) { //srs parameters amAudioSetSRSTrubassSpeakerSize(4); - amAudioSetSRSTrubassGain(0.3); - amAudioSetSRSDialogClarityGain(0.2); - amAudioSetSRSDefinitionGain(0.5); - amAudioSetSRSSurroundGain(0.6); + amAudioSetSRSTrubassGain(30); + amAudioSetSRSDialogClarityGain(20); + amAudioSetSRSDefinitionGain(50); + amAudioSetSRSSurroundGain(60); + amAudioSetSRSGain(50, 50); amAudioSetSRSDialogClaritySwitch(1); amAudioSetSRSSurroundSwitch(1); amAudioSetSRSTrubassSwitch(1); - sleep(500); amAudioClose(); diff --git a/libTVaudio/audio/aml_audio.c b/libTVaudio/audio/aml_audio.c index 4791eec..7a01406 100644 --- a/libTVaudio/audio/aml_audio.c +++ b/libTVaudio/audio/aml_audio.c @@ -20,6 +20,7 @@ #include <sys/mman.h> #include <sys/ioctl.h> #include <sys/stat.h> +#include <sys/prctl.h> #include <cutils/log.h> #include <cutils/properties.h> #include "tinyalsa/asoundlib.h" @@ -29,8 +30,9 @@ #define LOG_TAG "aml_audio" -#define ANDROID_OUT_BUFFER_SIZE (2048*8*2)//in byte -#define DDP_OUT_BUFFER_SIZE (2048*8*2)//in byte +#define ANDROID_OUT_BUFFER_SIZE (2048*8*2) //in byte +#define DDP_OUT_BUFFER_SIZE (2048*8*2*2*2) //in byte +#define DD_61937_BUFFER_SIZE (2048*8*2*2*2) #define DEFAULT_OUT_SAMPLE_RATE (48000) #define DEFAULT_IN_SAMPLE_RATE (48000) #define PLAYBACK_PERIOD_SIZE (512) @@ -61,7 +63,7 @@ static struct pcm_config pcm_config_in = { }; struct buffer_status { - short *start_add; + unsigned char *start_add; int size; int level; unsigned int rd; @@ -88,6 +90,9 @@ struct aml_stream_in { int max_bytes; void *temp_buffer; void *write_buffer; + int delay_time; + int last_delay_time; + struct circle_buffer delay_buf; }; struct aml_stream_out { @@ -97,15 +102,15 @@ struct aml_stream_out { int card; int device; int standby; - int max_bytes; void *temp_buffer; void *read_buffer; int output_device; int amAudio_OutHandle; struct buffer_status playback_buf; - struct buffer_status read_buf; - int amaudio_out_read_enable; int user_set_device; + int is_tv_platform; + int32_t *tmp_buffer_8ch; + void *audioeffect_tmp_buffer; }; struct aml_dev { @@ -117,10 +122,9 @@ struct aml_dev { int has_EQ_lib; int has_SRS_lib; int output_deviceID; + pthread_t android_check_ThreadID; }; -static void *start_temp_buffer = NULL; - static struct aml_dev gmAmlDevice = { .in = { .lock = PTHREAD_MUTEX_INITIALIZER, @@ -147,6 +151,15 @@ static struct aml_dev gmAmlDevice = { .max_bytes = 0, .temp_buffer = NULL, .write_buffer = NULL, + .delay_time = 0, + .last_delay_time = 0, + .delay_buf = { + .lock = PTHREAD_MUTEX_INITIALIZER, + .start_add = NULL, + .rd = NULL, + .wr = NULL, + .size = 0, + }, }, .out = { @@ -163,7 +176,6 @@ static struct aml_dev gmAmlDevice = { .card = 0, .device = 0, .standby = 0, - .max_bytes = 0, .temp_buffer = NULL, .read_buffer = NULL, .output_device = 0, @@ -175,15 +187,10 @@ static struct aml_dev gmAmlDevice = { .rd = 0, .wr = 0, }, - .read_buf = { - .start_add = NULL, - .size = 0, - .level = 0, - .rd = 0, - .wr = 0, - }, - .amaudio_out_read_enable = 0, .user_set_device = 0, + .is_tv_platform = 0, + .tmp_buffer_8ch = NULL, + .audioeffect_tmp_buffer = NULL, }, .aml_Audio_ThreadID = 0, @@ -192,6 +199,7 @@ static struct aml_dev gmAmlDevice = { .has_EQ_lib = 0, .has_SRS_lib = 0, .output_deviceID = 0, + .android_check_ThreadID = 0, }; struct circle_buffer android_out_buffer = { @@ -210,21 +218,32 @@ struct circle_buffer DDP_out_buffer = { .size = 0, }; +struct circle_buffer DD_out_buffer = { + .lock = PTHREAD_MUTEX_INITIALIZER, + .start_add = NULL, + .rd = NULL, + .wr = NULL, + .size = 0, +}; + +static void *start_temp_buffer = NULL; static struct aml_dev *gpAmlDevice = NULL; static pthread_mutex_t amaudio_dev_op_mutex = PTHREAD_MUTEX_INITIALIZER; +static unsigned int gUSBCheckLastFlag = 0; +static unsigned int gUSBCheckFlag = 0; extern int omx_codec_init(void); extern void omx_codec_close(void); extern int I2S_state; -#define PCM_DATA 0 -#define RAW_DATA 1 -#define HDMI_IN_AUDIO_TYPE "HDMI Audio Type" +#define I2S_IN_AUDIO_TYPE "I2SIN Audio Type" #define SPDIF_IN_AUDIO_TYPE "SPDIFIN Audio Type" #define Audio_In_Source_TYPE "Audio In Source" +#define HW_RESAMPLE_ENABLE "Hardware resample enable" #define AMAUDIO_IN "/dev/amaudio2_in" #define AMAUDIO_OUT "/dev/amaudio2_out" #define AMAUDIO2_PREENABLE "/sys/class/amaudio2/aml_amaudio2_enable" +#define AMAUDIO2_INPUTDEVICE "/sys/class/amaudio2/aml_input_device" #define AMAUDIO_IOC_MAGIC 'A' #define AMAUDIO_IOC_GET_SIZE _IOW(AMAUDIO_IOC_MAGIC, 0x00, int) @@ -235,12 +254,6 @@ extern int I2S_state; #define AMAUDIO_IOC_MIC_LEFT_GAIN _IOW(AMAUDIO_IOC_MAGIC, 0x05, int) #define AMAUDIO_IOC_MIC_RIGHT_GAIN _IOW(AMAUDIO_IOC_MAGIC, 0x06, int) #define AMAUDIO_IOC_MUSIC_GAIN _IOW(AMAUDIO_IOC_MAGIC, 0x07, int) -#define AMAUDIO_IOC_GET_PTR_READ _IOW(AMAUDIO_IOC_MAGIC, 0x08, int) -#define AMAUDIO_IOC_UPDATE_APP_PTR_READ _IOW(AMAUDIO_IOC_MAGIC, 0x09, int) -#define AMAUDIO_IOC_OUT_READ_ENABLE _IOW(AMAUDIO_IOC_MAGIC, 0x0a, int) -#define AMAUDIO_IOC_SET_ANDROID_VOLUME_ENABLE _IOW(AMAUDIO_IOC_MAGIC, 0x0b, int) -#define AMAUDIO_IOC_SET_ANDROID_LEFT_VOLUME _IOW(AMAUDIO_IOC_MAGIC, 0x0c, int) -#define AMAUDIO_IOC_SET_ANDROID_RIGHT_VOLUME _IOW(AMAUDIO_IOC_MAGIC, 0x0d, int) #define CC_DUMP_SRC_TYPE_INPUT (0) #define CC_DUMP_SRC_TYPE_OUTPUT (1) @@ -254,10 +267,28 @@ static int gDumpDataFd2 = -1; static int audioin_type = 0; static int omx_started = 0; static int raw_data_counter = 0; +static int pcm_data_counter = 0; +static int digital_raw_enable = 0; int output_record_enable = 0; +int spdif_audio_type = LPCM; pthread_mutex_t device_change_lock = PTHREAD_MUTEX_INITIALIZER; static void DoDumpData(void *data_buf, int size, int aud_src_type); +static int audio_effect_process(short* buffer, int frame_size); + +static int getprop_bool(const char * path) +{ + char buf[PROPERTY_VALUE_MAX]; + int ret = -1; + + ret = property_get(path, buf, NULL); + if (ret > 0) { + if (strcasecmp(buf, "true") == 0 || strcmp(buf, "1") == 0) + return 1; + } + + return 0; +} inline int GetWriteSpace(char *WritePoint, char *ReadPoint, int buffer_size) { int bytes; @@ -452,8 +483,6 @@ int buffer_write(struct circle_buffer *tmp, char* buffer, size_t bytes) { } size_t write_space = GetWriteSpace(buf->wr, buf->rd, buf->size); if (write_space < bytes) { - //tmp_buffer_reset(buf); - //ALOGD("%s, no space to write %d bytes to buffer.\n", __FUNCTION__,bytes); pthread_mutex_unlock(&buf->lock); return -1; } @@ -474,8 +503,6 @@ int buffer_read(struct circle_buffer *tmp, char* buffer, size_t bytes) { } size_t read_space = GetReadSpace(buf->wr, buf->rd, buf->size); if (read_space < bytes) { - //tmp_buffer_reset(buf); - //ALOGD("%s, no space to read %d bytes to buffer.\n", __FUNCTION__,bytes); pthread_mutex_unlock(&buf->lock); return -1; } @@ -496,12 +523,7 @@ static int set_input_stream_sample_rate(unsigned int sr, if (check_input_stream_sr(sr) == 0) { in->config.rate = sr; } else { - if (sr == 0) { - in->config.rate = pcm_config_in.rate; - } else { - ALOGE("%s, The sample rate (%u) is invalid!\n", __FUNCTION__, sr); - return -1; - } + in->config.rate = pcm_config_in.rate; } return 0; } @@ -542,12 +564,52 @@ static int get_aml_card(void) { return card; } +static int get_aml_device(int device_ID) { + int port = -1, err = 0; + int fd = -1; + unsigned fileSize = 512; + char *read_buf = NULL, *pd = NULL; + static const char *const SOUND_PCM_PATH = "/proc/asound/pcm"; + fd = open(SOUND_PCM_PATH, O_RDONLY); + if (fd < 0) { + ALOGE("ERROR: failed to open config file %s error: %d\n", SOUND_PCM_PATH, errno); + close(fd); + return -EINVAL; + } + + read_buf = (char *)malloc(fileSize); + if (!read_buf) { + ALOGE("Failed to malloc read_buf"); + close(fd); + return -ENOMEM; + } + memset(read_buf, 0x0, fileSize); + err = read(fd, read_buf, fileSize); + if (fd < 0) { + ALOGE("ERROR: failed to read config file %s error: %d\n", SOUND_PCM_PATH, errno); + close(fd); + return -EINVAL; + } + + if (device_ID == 1) { + pd = strstr(read_buf, "SPDIF"); + port = *(pd -3) - '0'; + } else if (device_ID == 0){ + pd = strstr(read_buf, "I2S"); + port = *(pd -3) - '0'; + } +OUT: + free(read_buf); + close(fd); + return port; +} + static int alsa_in_open(struct aml_stream_in *in) { in->config.channels = pcm_config_in.channels; in->config.period_size = pcm_config_in.period_size; in->config.period_count = pcm_config_in.period_count; in->config.format = pcm_config_in.format; - in->config.stop_threshold = CAPTURE_PERIOD_SIZE * CAPTURE_PERIOD_COUNT * 4; + in->config.stop_threshold = CAPTURE_PERIOD_SIZE * CAPTURE_PERIOD_COUNT * 10; in->standby = 1; in->resample_request = 0; in->resample_temp_buffer = NULL; @@ -567,8 +629,7 @@ static int alsa_in_open(struct aml_stream_in *in) { pthread_mutex_lock(&in->lock); in->card = get_aml_card(); - ALOGE("pcm in card ID = %d \n", in->card); - in->pcm = pcm_open(in->card, in->device, PCM_IN, &pcm_config_in); + in->pcm = pcm_open(in->card, in->device, PCM_IN, &(in->config)); if (!pcm_is_ready(in->pcm)) { ALOGE("%s, Unable to open PCM device in: %s\n", __FUNCTION__, pcm_get_error(in->pcm)); @@ -609,8 +670,16 @@ static int get_in_framesize(struct aml_stream_in *in) { return sample_format * in->config.channels; } +static void apply_stream_volume(float vol,char *buf,int size) { + int i; + short *sample = (short*)buf; + for (i = 0; i < size/sizeof(short); i++) + sample[i] = vol*sample[i]; +} + static int alsa_in_read(struct aml_stream_in *in, void* buffer, size_t bytes) { int ret; + int resample_request = in->resample_request; pthread_mutex_lock(&in->lock); if (in->standby) { @@ -620,11 +689,11 @@ static int alsa_in_read(struct aml_stream_in *in, void* buffer, size_t bytes) { } //if raw data in HDMI-in, no need to resample if (GetOutputdevice() == 2) { - in->resample_request == 0; + resample_request = 0; } int output_size = 0; - if (in->resample_request == 1) { + if (resample_request == 1) { ret = pcm_read(in->pcm, in->resample_temp_buffer, bytes); if (ret < 0) { //wait for next frame @@ -633,6 +702,10 @@ static int alsa_in_read(struct aml_stream_in *in, void* buffer, size_t bytes) { return ret; } + if (GetOutputdevice() != 2) { + float vol = get_android_stream_volume(); + apply_stream_volume(vol,in->resample_temp_buffer,bytes); + } DoDumpData(in->resample_temp_buffer, bytes, CC_DUMP_SRC_TYPE_INPUT); output_size = resample_process(in, bytes >> 2, @@ -642,10 +715,16 @@ static int alsa_in_read(struct aml_stream_in *in, void* buffer, size_t bytes) { if (ret < 0) { //wait for next frame usleep(bytes * 1000000 / get_in_framesize(in) / in->config.rate); + ALOGE("Can't read data from alsa!\n"); pthread_mutex_unlock(&in->lock); return ret; } + if (GetOutputdevice() != 2 && + (gUSBCheckFlag & AUDIO_DEVICE_OUT_SPEAKER) != 0) { + float vol = get_android_stream_volume(); + apply_stream_volume(vol,buffer,bytes); + } DoDumpData(buffer, bytes, CC_DUMP_SRC_TYPE_INPUT); output_size = bytes; @@ -655,19 +734,33 @@ static int alsa_in_read(struct aml_stream_in *in, void* buffer, size_t bytes) { } static int alsa_out_open(struct aml_stream_out *out) { - out->config.channels = pcm_config_out.channels; - out->config.rate = pcm_config_out.rate; out->config.period_size = pcm_config_out.period_size; + out->config.rate = pcm_config_out.rate; out->config.period_count = pcm_config_out.period_count; - out->config.format = pcm_config_out.format; - out->config.stop_threshold = PLAYBACK_PERIOD_SIZE * PLAYBACK_PERIOD_COUNT; out->standby = 1; - out->max_bytes = out->config.period_size << 2; - out->amaudio_out_read_enable = 0; + if (getprop_bool("ro.platform.has.tvuimode")) { + out->config.channels = 8; + out->config.format = PCM_FORMAT_S32_LE; + out->tmp_buffer_8ch = malloc(out->config.period_size * 4 * 8); /*8 channel, 32bit*/ + if (out->tmp_buffer_8ch == NULL) { + ALOGE("cannot malloc memory for out->tmp_buffer_8ch"); + return -ENOMEM; + } + out->audioeffect_tmp_buffer = malloc(out->config.period_size * 6); + if (out->audioeffect_tmp_buffer == NULL) { + ALOGE("cannot malloc memory for audioeffect_tmp_buffer"); + return -ENOMEM; + } + out->is_tv_platform = 1; + }else { + out->config.channels = pcm_config_out.channels; + out->config.format = pcm_config_out.format; + out->is_tv_platform = 0; + } pthread_mutex_lock(&out->lock); out->card = get_aml_card(); - out->pcm = pcm_open(out->card, out->device, PCM_OUT, &pcm_config_out); + out->pcm = pcm_open(out->card, out->device, PCM_OUT, &(out->config)); if (!pcm_is_ready(out->pcm)) { ALOGE("%s, Unable to open PCM device out: %s\n", __FUNCTION__, pcm_get_error(out->pcm)); @@ -686,6 +779,11 @@ static int alsa_out_close(struct aml_stream_out *out) { ALOGD("%s, Do output close!\n", __FUNCTION__); pthread_mutex_lock(&out->lock); + if (out->is_tv_platform == 1) { + free(out->tmp_buffer_8ch); + free(out->audioeffect_tmp_buffer); + out->is_tv_platform = 0; + } if (!out->standby) { pcm_close(out->pcm); out->pcm = NULL; @@ -705,6 +803,7 @@ static int get_out_framesize(struct aml_stream_out *out) { static int alsa_out_write(struct aml_stream_out *out, void* buffer, size_t bytes) { int ret; + int input_frames = bytes >> 2; pthread_mutex_lock(&out->lock); if (out->standby) { @@ -713,7 +812,29 @@ static int alsa_out_write(struct aml_stream_out *out, void* buffer, return 0; } - ret = pcm_write(out->pcm, buffer, bytes); + if (out->is_tv_platform == 1) { + int16_t *tmp_buffer = (int16_t *)out->audioeffect_tmp_buffer; + int16_t *in_buffer = (int16_t *)buffer; + int out_byte = input_frames * 32; + int i = 0; + memcpy((void *)tmp_buffer, buffer, bytes); + audio_effect_process(tmp_buffer, input_frames); + for (i = 0; i < input_frames; i ++) { + out->tmp_buffer_8ch[8*i] = ((int32_t)(in_buffer[2*i])) << 16; + out->tmp_buffer_8ch[8*i + 1] = ((int32_t)(in_buffer[2*i + 1])) << 16; + out->tmp_buffer_8ch[8*i + 2] = ((int32_t)(tmp_buffer[2*i])) << 16; + out->tmp_buffer_8ch[8*i + 3] = ((int32_t)(tmp_buffer[2*i + 1])) << 16; + out->tmp_buffer_8ch[8*i + 4] = 0; + out->tmp_buffer_8ch[8*i + 5] = 0; + out->tmp_buffer_8ch[8*i + 6] = 0; + out->tmp_buffer_8ch[8*i + 7] = 0; + } + ret = pcm_write(out->pcm, out->tmp_buffer_8ch, out_byte); + } else { + audio_effect_process((short *)buffer, input_frames); + ret = pcm_write(out->pcm, buffer, bytes); + } + if (ret < 0) { usleep(bytes * 1000000 / get_out_framesize(out) / out->config.rate); pthread_mutex_unlock(&out->lock); @@ -729,10 +850,6 @@ static int reset_amaudio(struct aml_stream_out *out, int delay_size) { buf->rd = 0; buf->wr = 0; buf->level = buf->size; - struct buffer_status *buf1 = &out->read_buf; - buf1->rd = 0; - buf1->wr = 0; - buf1->level = 0; int ret = ioctl(out->amAudio_OutHandle, AMAUDIO_IOC_RESET, delay_size); if (ret < 0) { ALOGE("%s, amaudio reset delay_size error!\n", __FUNCTION__); @@ -754,6 +871,21 @@ static int set_amaudio2_enable(int flag) { close(fd); return 0; } + +static int set_input_device(int flag) { + int fd = 0; + char string[16]; + fd = open(AMAUDIO2_INPUTDEVICE, O_CREAT | O_RDWR, 0664); + if (fd < 0) { + ALOGE("unable to open file %s \n", AMAUDIO2_INPUTDEVICE); + return -1; + } + sprintf(string, "%d", flag); + write(fd, string, strlen(string)); + close(fd); + return 0; +} + static int new_audiotrack(struct aml_stream_out *out) { int i = 0, ret = 0; int dly_tm = 20 * 1000, dly_cnt = 1000; //20s @@ -815,16 +947,29 @@ static int release_audiotrack(struct aml_stream_out *out) { } static int amaudio_out_open(struct aml_stream_out *out) { - - out->config.channels = pcm_config_out.channels; - out->config.rate = pcm_config_out.rate; out->config.period_size = pcm_config_out.period_size; + out->config.rate = pcm_config_out.rate; out->config.period_count = pcm_config_out.period_count; - out->config.format = pcm_config_out.format; - out->standby = 1; - out->max_bytes = out->config.period_size << 2; - out->amaudio_out_read_enable = 0; + if (getprop_bool("ro.platform.has.tvuimode")) { + out->config.channels = 8; + out->config.format = PCM_FORMAT_S32_LE; + out->tmp_buffer_8ch = malloc(out->config.period_size * 4 * 8); /*8 channel, 32bit*/ + if (out->tmp_buffer_8ch == NULL) { + ALOGE("cannot malloc memory for out->tmp_buffer_8ch"); + return -ENOMEM; + } + out->audioeffect_tmp_buffer = malloc(out->config.period_size * 6); + if (out->audioeffect_tmp_buffer == NULL) { + ALOGE("cannot malloc memory for audioeffect_tmp_buffer"); + return -ENOMEM; + } + out->is_tv_platform = 1; + }else { + out->config.channels = pcm_config_out.channels; + out->config.format = pcm_config_out.format; + out->is_tv_platform = 0; + } pthread_mutex_lock(&out->lock); out->amAudio_OutHandle = -1; @@ -851,9 +996,6 @@ static int amaudio_out_open(struct aml_stream_out *out) { return -1; } - struct buffer_status *buf1 = &out->read_buf; - buf1->size = buf->size; - out->standby = 0; pthread_mutex_unlock(&out->lock); ALOGD("%s, Amaudio device is opened!\n", __FUNCTION__); @@ -863,6 +1005,10 @@ static int amaudio_out_open(struct aml_stream_out *out) { static int amaudio_out_close(struct aml_stream_out *out) { ALOGD("%s, Do amaudio device close!\n", __FUNCTION__); pthread_mutex_lock(&out->lock); + if (out->is_tv_platform == 1) { + free(out->tmp_buffer_8ch); + free(out->audioeffect_tmp_buffer); + } if (out->amAudio_OutHandle > 0) { close(out->amAudio_OutHandle); out->amAudio_OutHandle = -1; @@ -874,95 +1020,73 @@ static int amaudio_out_close(struct aml_stream_out *out) { static int amaudio_out_write(struct aml_stream_out *out, void* buffer, size_t bytes) { - int block = bytes >> 6 << 6; //align 2^6 - char *in_ptr = (char *) buffer; - char *out_ptr = NULL; - - int k = 0, i = 0; struct buffer_status *buf = &out->playback_buf; + int input_frames = bytes >> 2; + unsigned char *out_buffer = NULL; pthread_mutex_lock(&out->lock); - //get rd ptr, and calculate write space - buf->rd = ioctl(out->amAudio_OutHandle, AMAUDIO_IOC_GET_PTR); - buf->level = buf->size - ((buf->size + buf->wr - buf->rd) % buf->size); - - if (buf->level <= block) { - ALOGD("Reset amaudio: buf->level=%x,buf->rd = %x,buf->wr=%x\n", - buf->level, buf->rd, buf->wr); - pthread_mutex_unlock(&out->lock); - return -1; - } - - out_ptr = &(buf->start_add[buf->wr / 2]); - memcpy(out_ptr, in_ptr, block); - - // update the write pointer and write space - buf->wr = (buf->wr + block) % buf->size; - buf->level = buf->size - ((buf->size + buf->wr - buf->rd) % buf->size); - ioctl(out->amAudio_OutHandle, AMAUDIO_IOC_UPDATE_APP_PTR, buf->wr); - pthread_mutex_unlock(&out->lock); - - return block; -} - -int amaudio_out_read_enable(int enable) { - int ret; - - if (gpAmlDevice == NULL) { - ALOGE("%s, aml audio is not open, must open it first!\n", __FUNCTION__); - return -1; - } + if (out->is_tv_platform == 1) { + int16_t *tmp_buffer = (int16_t *)out->audioeffect_tmp_buffer; + int16_t *in_buffer = (int16_t *)buffer; + int out_byte = input_frames * 32; + int i = 0; + + memcpy((void *)tmp_buffer, buffer, bytes); + audio_effect_process(tmp_buffer, input_frames); + for (i = 0; i < input_frames; i ++) { + out->tmp_buffer_8ch[8*i] = ((int32_t)(in_buffer[2*i])) << 16; + out->tmp_buffer_8ch[8*i + 1] = ((int32_t)(in_buffer[2*i + 1])) << 16; + out->tmp_buffer_8ch[8*i + 2] = ((int32_t)(tmp_buffer[2*i])) << 16; + out->tmp_buffer_8ch[8*i + 3] = ((int32_t)(tmp_buffer[2*i + 1])) << 16; + out->tmp_buffer_8ch[8*i + 4] = 0; + out->tmp_buffer_8ch[8*i + 5] = 0; + out->tmp_buffer_8ch[8*i + 6] = 0; + out->tmp_buffer_8ch[8*i + 7] = 0; + } - int OutHandle = gpAmlDevice->out.amAudio_OutHandle; - if (OutHandle < 0) { - ALOGE("%s, amaudio out handle error!\n", __FUNCTION__); - return -1; - } + //get rd ptr, and calculate write space + buf->rd = ioctl(out->amAudio_OutHandle, AMAUDIO_IOC_GET_PTR); + buf->level = buf->size - ((buf->size + buf->wr - buf->rd) % buf->size); - pthread_mutex_lock(&gpAmlDevice->out.lock); - gpAmlDevice->out.amaudio_out_read_enable = enable; - reset_amaudio(&gpAmlDevice->out, 64 * 32 * 2); - ioctl(OutHandle, AMAUDIO_IOC_OUT_READ_ENABLE, enable); - ALOGD("%s, out read enable :%d!\n", __FUNCTION__, enable); - pthread_mutex_unlock(&gpAmlDevice->out.lock); - return 0; -} + if (buf->level <= out_byte) { + ALOGD("Reset amaudio: buf->level=%x,buf->rd = %x,buf->wr=%x\n", + buf->level, buf->rd, buf->wr); + pthread_mutex_unlock(&out->lock); + return -1; + } + out_buffer = buf->start_add + buf->wr; + memcpy((void *)out_buffer, (void *)out->tmp_buffer_8ch, out_byte); -static int amaudio_out_read(struct aml_stream_out *out, void* buffer, - size_t bytes) { - int block = bytes >> 6 << 6; //align 2^6 - char *in = (char *) buffer; - struct buffer_status *buf = &out->read_buf; + // update the write pointer and write space + buf->wr = (buf->wr + out_byte) % buf->size; + buf->level = buf->size - ((buf->size + buf->wr - buf->rd) % buf->size); + ioctl(out->amAudio_OutHandle, AMAUDIO_IOC_UPDATE_APP_PTR, buf->wr); - pthread_mutex_lock(&out->lock); + } else { + audio_effect_process((short *)buffer, input_frames); - buf->wr = ioctl(out->amAudio_OutHandle, AMAUDIO_IOC_GET_PTR_READ); - buf->level = (buf->size + buf->wr - buf->rd) % buf->size; + //get rd ptr, and calculate write space + buf->rd = ioctl(out->amAudio_OutHandle, AMAUDIO_IOC_GET_PTR); + buf->level = buf->size - ((buf->size + buf->wr - buf->rd) % buf->size); - if (buf->level < block) { - usleep(5000); - pthread_mutex_unlock(&out->lock); - ALOGD("buf->level=%d,buf->rd = %d,buf->wr=%d\n", buf->level, buf->rd, - buf->wr); - return 0; - } + if (buf->level <= bytes) { + ALOGD("Reset amaudio: buf->level=%x,buf->rd = %x,buf->wr=%x\n", + buf->level, buf->rd, buf->wr); + pthread_mutex_unlock(&out->lock); + return -1; + } + out_buffer = buf->start_add + buf->wr; + memcpy((void *)out_buffer, buffer, bytes); - int Ret = read(out->amAudio_OutHandle, (char *) buffer, block); - if (Ret != block) { - ALOGE("%s, amAudio2 read from hardware buffer failed!\n", __FUNCTION__); - pthread_mutex_unlock(&out->lock); - return -1; + // update the write pointer and write space + buf->wr = (buf->wr + bytes) % buf->size; + buf->level = buf->size - ((buf->size + buf->wr - buf->rd) % buf->size); + ioctl(out->amAudio_OutHandle, AMAUDIO_IOC_UPDATE_APP_PTR, buf->wr); } - // update the read pointer - buf->rd += block; - buf->rd %= buf->size; - buf->level = (buf->size + buf->wr - buf->rd) % buf->size; - - ioctl(out->amAudio_OutHandle, AMAUDIO_IOC_UPDATE_APP_PTR_READ, buf->rd); pthread_mutex_unlock(&out->lock); - return block; + return bytes; } static int malloc_buffer(struct aml_dev *device) { @@ -1034,6 +1158,14 @@ static int set_output_deviceID(int deviceID) { return 0; } +static int get_output_deviceID(void) { + if (gpAmlDevice == NULL) { + ALOGE("%s, aml audio is not open, must open it first!\n", __FUNCTION__); + return -1; + } + return gpAmlDevice->output_deviceID; +} + static int aml_device_init(struct aml_dev *device) { int ret; @@ -1051,7 +1183,12 @@ static int aml_device_init(struct aml_dev *device) { ALOGE("%s, malloc ddp buffer failed!\n", __FUNCTION__); goto error2; } - + // add a temp buffer to store dd 61937 audio frame + ret = tmp_buffer_init(&DD_out_buffer, DD_61937_BUFFER_SIZE); + if (ret < 0) { + ALOGE("%s, malloc dd 61937 buffer failed!\n", __FUNCTION__); + goto error3; + } //open input device of tinyalsa ret = alsa_in_open(&device->in); if (ret < 0) { @@ -1132,6 +1269,7 @@ static int aml_device_init(struct aml_dev *device) { error5: release_buffer(device); error4: alsa_in_close(&device->in); error3: tmp_buffer_release (&DDP_out_buffer); + tmp_buffer_release (&DD_out_buffer); error2: tmp_buffer_release (&android_out_buffer); error1: return ret; @@ -1143,6 +1281,10 @@ static int aml_device_close(struct aml_dev *device) { alsa_in_close(in); + if (in->delay_buf.size != 0) { + free(in->delay_buf.start_add); + } + if (out->output_device == CC_OUT_USE_ALSA) { alsa_out_close(out); } else if (out->output_device == CC_OUT_USE_AMAUDIO) { @@ -1154,15 +1296,13 @@ static int aml_device_close(struct aml_dev *device) { omx_codec_close(); omx_started = 0; tmp_buffer_release (&DDP_out_buffer); + tmp_buffer_release (&DD_out_buffer); tmp_buffer_release (&android_out_buffer); release_buffer(device); audio_effect_release(); return 0; } -static int gUSBCheckLastFlag = 0; -static int gUSBCheckFlag = 0; - static void USB_check(struct aml_stream_out *out) { gUSBCheckFlag = GetUsbAudioCheckFlag(); @@ -1217,7 +1357,7 @@ static int get_channel_status(void) { struct mixer *pmixer; struct mixer_ctl *pctl; int card_id; - int type_HDMI = -1; + int type_I2S = -1; int type_SPDIF = -1; int type_AUDIO_IN = -1; @@ -1232,7 +1372,7 @@ static int get_channel_status(void) { type_AUDIO_IN = mixer_ctl_get_value(pctl, 0); if (type_AUDIO_IN != 2) { mixer_close(pmixer); - return PCM_DATA; + return LPCM; } } @@ -1241,25 +1381,48 @@ static int get_channel_status(void) { type_SPDIF = mixer_ctl_get_value(pctl, 0); } - pctl = mixer_get_ctl_by_name(pmixer, HDMI_IN_AUDIO_TYPE); + pctl = mixer_get_ctl_by_name(pmixer, I2S_IN_AUDIO_TYPE); if (NULL != pctl) { - type_HDMI = mixer_ctl_get_value(pctl, 0); + type_I2S = mixer_ctl_get_value(pctl, 0); } - if (type_SPDIF == RAW_DATA || type_HDMI == RAW_DATA) { - mixer_close(pmixer); - return RAW_DATA; - } else { + if (type_SPDIF == LPCM && type_I2S == AC3) { mixer_close(pmixer); - return PCM_DATA; + return MUTE; } - err_exit: if (NULL != pmixer) { + + mixer_close(pmixer); + return type_SPDIF; + +err_exit: + if (NULL != pmixer) { mixer_close(pmixer); } return -1; } -static int set_rawdata_in_enable(struct aml_stream_out *out) { +static int set_Hardware_resample(int enable) { +
struct mixer *pmixer; + struct mixer_ctl *pctl; +
int card_id; + card_id = get_aml_card(); + pmixer = mixer_open(card_id); + if (NULL == pmixer) { + ALOGE("[%s:%d] Failed to open mixer\n", __FUNCTION__, __LINE__); + goto err_exit; + } + pctl = mixer_get_ctl_by_name(pmixer, HW_RESAMPLE_ENABLE); + if (NULL != pctl) { + mixer_ctl_set_value(pctl, 0, enable); + } +err_exit: + if (NULL != pmixer) { + mixer_close(pmixer); + } + return -1; + } + + static int set_rawdata_in_enable(struct aml_stream_out *out) { if (out->output_device == CC_OUT_USE_AMAUDIO) { amaudio_out_close(out); } else if (out->output_device == CC_OUT_USE_ALSA) { @@ -1268,13 +1431,15 @@ static int set_rawdata_in_enable(struct aml_stream_out *out) { } set_output_deviceID(2); out->output_device = CC_OUT_USE_ANDROID; + set_Hardware_resample(4); + digital_raw_enable = amsysfs_get_sysfs_int("/sys/class/audiodsp/digital_raw"); omx_codec_init(); return 0; } static int set_rawdata_in_disable(struct aml_stream_out *out) { omx_codec_close(); - if (gUSBCheckFlag == 0) { + if ((gUSBCheckFlag & AUDIO_DEVICE_OUT_SPEAKER) != 0) { if (out->user_set_device == CC_OUT_USE_AMAUDIO) { set_output_deviceID(0); amaudio_out_open(out); @@ -1288,10 +1453,11 @@ static int set_rawdata_in_disable(struct aml_stream_out *out) { set_output_deviceID(0); out->output_device = CC_OUT_USE_ALSA; } - } else if (gUSBCheckFlag == 1) { + } else { set_output_deviceID(1); out->output_device = CC_OUT_USE_ANDROID; } + set_Hardware_resample(5); return 0; } @@ -1312,25 +1478,102 @@ int set_output_record_enable(int enable) { static int check_audio_type(struct aml_stream_out *out) { audioin_type = get_channel_status(); - - if (audioin_type == 1 && omx_started == 0) { + if (audioin_type == MUTE) + return MUTE; + spdif_audio_type = audioin_type; + if (audioin_type > LPCM && omx_started == 0) { raw_data_counter++; } - - if (raw_data_counter >= 3 && omx_started == 0) { - ALOGI("%s, audio type is changed to RAW data input!\n", __FUNCTION__); + if (audioin_type == LPCM && omx_started == 1) { + pcm_data_counter++; + } + if (raw_data_counter >= 1 && omx_started == 0) { + ALOGI("%s, audio type is changed to RAW data input!,type %d\n", __FUNCTION__,audioin_type); set_rawdata_in_enable(out); omx_started = 1; raw_data_counter = 0; - } else if (audioin_type == 0 && omx_started == 1) { - ALOGI("%s, audio type is changed to PCM data input!\n", __FUNCTION__); + } else if (pcm_data_counter >= 1 && omx_started == 1) { + ALOGI("%s, audio type is changed to PCM data input!,type %d\n", __FUNCTION__,audioin_type); set_rawdata_in_disable(out); omx_started = 0; + pcm_data_counter = 0; + } + /* + if omx ddp decoder has been started, but user configure pcm ->raw output + we need reset decoder to enable decoder to dd/dd+ converter + */ + else if (omx_started == 1) { + int digtal_out = amsysfs_get_sysfs_int("/sys/class/audiodsp/digital_raw"); + int need_reset_config = 0; + if (audioin_type == EAC3 && digtal_out != digital_raw_enable) { + ALOGI("DD+ passthrough flag changed from %d to %d\n",digital_raw_enable,digtal_out); + need_reset_config = 1; + } + else if (digtal_out > 0 && digital_raw_enable == 0) { + ALOGI("PCM output changed to RAW pass through\n"); + need_reset_config = 1; + } + if (need_reset_config) { + ALOGI("pcm to pass through,decoder to reset \n"); + set_rawdata_in_disable(out); + set_rawdata_in_enable(out); + //omx_started = 0; + } } return 0; } -static void* aml_audio_threadloop(void *data) { +static int audio_effect_process(short* buffer, int frame_size) { + int output_size = frame_size << 2; + if (gpAmlDevice->has_SRS_lib) { + output_size = srs_process(buffer, buffer, frame_size); + } + if (gpAmlDevice->has_EQ_lib) { + HPEQ_process(buffer, buffer, frame_size); + } + return output_size; +} + +static int set_delay(struct aml_stream_in *in, int frame_size) { + unsigned char *buffer_ptr = NULL; + int delay_buffer_size = in->delay_time * 192; + int buffer_size = delay_buffer_size + frame_size; + + if (in->delay_buf.size < buffer_size) { + in->delay_buf.start_add = (char *)realloc( + in->delay_buf.start_add, buffer_size * sizeof(char)); + if (!in->delay_buf.start_add) { + ALOGE("realloc delay buffer failed\n"); + return -1; + } + memset(in->delay_buf.start_add, 0, in->delay_buf.size); + in->delay_buf.size = buffer_size; + in->delay_buf.rd = in->delay_buf.start_add; + in->delay_buf.wr = in->delay_buf.start_add + delay_buffer_size; + ALOGI("realloc delay buffer size %d byte\n", buffer_size); + } + + if (in->last_delay_time != in->delay_time) { + in->delay_buf.wr = in->delay_buf.rd + delay_buffer_size; + if (in->delay_buf.wr >= (in->delay_buf.start_add + in->delay_buf.size)) + in->delay_buf.wr -= in->delay_buf.size; + in->last_delay_time = in->delay_time; + } + + write_to_buffer(in->delay_buf.wr, in->temp_buffer, frame_size, + in->delay_buf.start_add, in->delay_buf.size); + in->delay_buf.wr = update_pointer(in->delay_buf.wr, frame_size, + in->delay_buf.start_add, in->delay_buf.size); + + read_from_buffer(in->delay_buf.rd, in->temp_buffer, frame_size, + in->delay_buf.start_add, in->delay_buf.size); + in->delay_buf.rd = update_pointer(in->delay_buf.rd, frame_size, + in->delay_buf.start_add, in->delay_buf.size); + + return 0; +} + +static void* aml_audio_threadloop(void *data __unused) { struct aml_stream_in *in = NULL; struct aml_stream_out *out = NULL; int output_size = 0; @@ -1344,10 +1587,9 @@ static void* aml_audio_threadloop(void *data) { in = &gpAmlDevice->in; out = &gpAmlDevice->out; - out->max_bytes = pcm_config_out.period_size << 2; gpAmlDevice->aml_Audio_ThreadExecFlag = 1; - ALOGD("%s, set aml_Audio_ThreadExecFlag as 1.\n", __FUNCTION__); + /*ALOGD("%s, set aml_Audio_ThreadExecFlag as 1.\n", __FUNCTION__);*/ if (gpAmlDevice->out.user_set_device == CC_OUT_USE_AMAUDIO) { int delay_size = 64 * 32 * 2; //less than 10.67*2 ms delay @@ -1371,9 +1613,10 @@ static void* aml_audio_threadloop(void *data) { if (output_size < 0) { //ALOGE("%s, alsa_in_read fail!\n", __FUNCTION__); } else { - if (gpAmlDevice->has_EQ_lib && (GetOutputdevice() == 0)) { - HPEQ_process((short *) in->temp_buffer, - (short *) in->temp_buffer, output_size >> 2); + if (check_audio_type(out) == MUTE) + memset((char *) in->temp_buffer, 0, output_size); + if (in->delay_time != 0 && get_output_deviceID() == 0) { + set_delay(in, output_size); } write_to_buffer((char *) in->write_buffer, (char *) in->temp_buffer, output_size, @@ -1381,7 +1624,6 @@ static void* aml_audio_threadloop(void *data) { in->write_buffer = update_pointer((char *) in->write_buffer, output_size, (char *) start_temp_buffer, TEMP_BUFFER_SIZE); - check_audio_type(out); } } @@ -1389,16 +1631,12 @@ static void* aml_audio_threadloop(void *data) { USB_check(out); if (GetReadSpace((char *) in->write_buffer, (char *) out->read_buffer, - TEMP_BUFFER_SIZE) > out->max_bytes) { + TEMP_BUFFER_SIZE) > pcm_config_out.period_size << 2) { read_from_buffer((char *) out->read_buffer, - (char *) out->temp_buffer, out->max_bytes, + (char *) out->temp_buffer, pcm_config_out.period_size << 2, (char *) start_temp_buffer, TEMP_BUFFER_SIZE); - output_size = out->max_bytes; - if (gpAmlDevice->has_SRS_lib && (GetOutputdevice() == 0)) { - output_size = srs_process((short *) out->temp_buffer, - (short *) out->temp_buffer, out->max_bytes >> 2); - } + output_size = pcm_config_out.period_size << 2; if (gpAmlDevice->out.output_device == CC_OUT_USE_ALSA) { output_size = alsa_out_write(out, out->temp_buffer, output_size); @@ -1467,7 +1705,8 @@ int aml_audio_open(unsigned int sr, int input_device, int output_device) { struct sched_param param; int ret; - ALOGD("%s, sr = %d, output_device = %d\n", __FUNCTION__, sr, output_device); + ALOGD("%s, sr = %d, input_device = %d, output_device = %d\n", + __FUNCTION__, sr, input_device, output_device); aml_audio_close(); @@ -1498,8 +1737,12 @@ int aml_audio_open(unsigned int sr, int input_device, int output_device) { gpAmlDevice->out.user_set_device = CC_OUT_USE_AMAUDIO; } - gpAmlDevice->in.device = input_device; + ret = set_input_device(input_device); + if (ret < 0) { + ALOGE("Fail to set input device for HW resample!\n"); + } + gpAmlDevice->in.device = get_aml_device(input_device); ret = aml_device_init(gpAmlDevice); if (ret < 0) { ALOGE("%s, Devices fail opened!\n", __FUNCTION__); @@ -1512,11 +1755,13 @@ int aml_audio_open(unsigned int sr, int input_device, int output_device) { pthread_attr_init(&attr); pthread_attr_setschedpolicy(&attr, SCHED_RR); param.sched_priority = sched_get_priority_max(SCHED_RR); + /*pthread_attr_setschedpolicy(&attr, SCHED_FIFO); + param.sched_priority = sched_get_priority_max(SCHED_FIFO); + ALOGD("%s, aml_audio thread has %d priority!\n", + __FUNCTION__, param.sched_priority);*/ pthread_attr_setschedparam(&attr, ¶m); gpAmlDevice->aml_Audio_ThreadTurnOnFlag = 1; - ALOGD("%s, set aml_Audio_ThreadTurnOnFlag as 1.\n", __FUNCTION__); gpAmlDevice->aml_Audio_ThreadExecFlag = 0; - ALOGD("%s, set aml_Audio_ThreadExecFlag as 0.\n", __FUNCTION__); ret = pthread_create(&gpAmlDevice->aml_Audio_ThreadID, &attr, &aml_audio_threadloop, NULL); pthread_attr_destroy(&attr); @@ -1528,6 +1773,9 @@ int aml_audio_open(unsigned int sr, int input_device, int output_device) { pthread_mutex_unlock(&amaudio_dev_op_mutex); return -1; } + prctl(PR_SET_NAME, (unsigned long)"aml_TV_audio"); + + creat_pthread_for_android_check(&gpAmlDevice->android_check_ThreadID); pthread_mutex_unlock(&amaudio_dev_op_mutex); @@ -1549,19 +1797,15 @@ int aml_audio_close(void) { if (gpAmlDevice->aml_Audio_ThreadExecFlag == 0) { break; } - if (i >= tmp_timeout_count) { break; } - i++; - usleep(10 * 1000); } if (i >= tmp_timeout_count) { - ALOGE( - "%s, we have try %d times, but the aml audio thread's exec flag is still(%d)!!!\n", + ALOGE("%s, we have try %d times, but the aml audio thread's exec flag is still(%d)!!!\n", __FUNCTION__, tmp_timeout_count, gpAmlDevice->aml_Audio_ThreadExecFlag); } else { @@ -1572,6 +1816,9 @@ int aml_audio_close(void) { pthread_join(gpAmlDevice->aml_Audio_ThreadID, NULL); gpAmlDevice->aml_Audio_ThreadID = 0; + exit_pthread_for_android_check(gpAmlDevice->android_check_ThreadID); + gpAmlDevice->android_check_ThreadID = 0; + aml_device_close(gpAmlDevice); clrDevice(gpAmlDevice); gpAmlDevice = NULL; @@ -1590,53 +1837,6 @@ int check_input_stream_sr(unsigned int sr) { return -1; } -int set_android_volume_enable(int enable) { - if (amaudio2_out_handle < 0) { - amaudio2_out_handle = open(AMAUDIO_OUT, O_RDWR); - if (amaudio2_out_handle < 0) { - ALOGE("%s, The device amaudio_out cant't be opened!\n", - __FUNCTION__); - return -1; - } - ALOGI("%s, get amaudio2 handle = %d!\n", __FUNCTION__, - amaudio2_out_handle); - } - - if (enable != 0 && enable != 1) { - ALOGE("invalid value: enable = %d. (warning: 0 or 1 is valid)\n", - enable); - return -1; - } - - ioctl(amaudio2_out_handle, AMAUDIO_IOC_SET_ANDROID_VOLUME_ENABLE, enable); - - return 0; -} - -int set_android_volume(int left, int right) { - if (amaudio2_out_handle < 0) { - amaudio2_out_handle = open(AMAUDIO_OUT, O_RDWR); - if (amaudio2_out_handle < 0) { - ALOGE("%s, The device amaudio_out cant't be opened!\n", - __FUNCTION__); - return -1; - } - ALOGI("%s, get amaudio2 handle = %d!\n", __FUNCTION__, - amaudio2_out_handle); - } - - if (left < 0 || left > 256 || right < 0 || right > 256) { - ALOGE( - "invalid value: left = %d, right = %d. (warning: 0-256 is valid)\n", - left, right); - return -1; - } - - ioctl(amaudio2_out_handle, AMAUDIO_IOC_SET_ANDROID_LEFT_VOLUME, left); - ioctl(amaudio2_out_handle, AMAUDIO_IOC_SET_ANDROID_RIGHT_VOLUME, right); - return 0; -} - int set_output_mode(int mode) { if (gpAmlDevice == NULL) { ALOGE("%s, aml audio is not open, must open it first!\n", __FUNCTION__); @@ -1732,6 +1932,16 @@ int set_right_gain(int right_gain) { return 0; } +int set_audio_delay(int delay_ms) { + gpAmlDevice->in.delay_time = delay_ms; + ALOGI("Set audio delay time %d ms!\n", delay_ms); + return 0; +} + +int get_audio_delay(void) { + return gpAmlDevice->in.delay_time; +} + int SetDumpDataFlag(int tmp_flag) { int tmp_val; tmp_val = gDumpDataFlag; diff --git a/libTVaudio/audio/aml_audio.h b/libTVaudio/audio/aml_audio.h index 1e37f07..e0cd909 100644 --- a/libTVaudio/audio/aml_audio.h +++ b/libTVaudio/audio/aml_audio.h @@ -43,7 +43,15 @@ struct circle_buffer { char *wr; int size; }; - +enum { + LPCM = 0, + AC3, + EAC3, + DTS, + DTSHD, + TRUEHD, + MUTE, +}; /* In this system, input stream sample rate can be set from 8K-48K, and output sample rate is fixed 48K. When input stream sample rate is different from output, inlined reample is in operation. If input stream sr is not set, @@ -61,10 +69,9 @@ int set_left_gain(int left_gain); int set_right_gain(int right_gain); int buffer_read(struct circle_buffer *tmp, char* buffer, size_t bytes); int buffer_write(struct circle_buffer *tmp, char* buffer, size_t bytes); -int getUSBCheckFlag(); -int set_android_volume_enable(int enable); -int set_android_volume(int left, int right); int set_output_record_enable(int enable); +int set_audio_delay(int delay_ms); +int get_audio_delay(void); #ifdef __cplusplus } diff --git a/libTVaudio/audio/android_out.cpp b/libTVaudio/audio/android_out.cpp index 65922d9..559df95 100644 --- a/libTVaudio/audio/android_out.cpp +++ b/libTVaudio/audio/android_out.cpp @@ -1,14 +1,13 @@ -/* - android_out.cpp - New an audio track in android, but no data in this track. Only push FIFO pointer. - */ - #include <stdio.h> #include <string.h> #include <stdlib.h> #include <pthread.h> +#include <fcntl.h> +#include <errno.h> +#include <strings.h> +#include <sys/ioctl.h> #include <cutils/log.h> - +#include <cutils/properties.h> #include <media/AudioTrack.h> #include "audio_usb_check.h" @@ -21,18 +20,79 @@ using namespace android; #define LOG_TAG "android_out" static AudioTrack *glpTracker = NULL; +static AudioTrack *glpTracker_raw = NULL; -#if ANDROID_PLATFORM_SDK_VERSION >= 19 static sp<AudioTrack> gmpAudioTracker; -#endif +static sp<AudioTrack> gmpAudioTracker_raw; extern struct circle_buffer android_out_buffer; extern struct circle_buffer DDP_out_buffer; +extern struct circle_buffer DD_out_buffer; extern int output_record_enable; +extern int spdif_audio_type; extern pthread_mutex_t device_change_lock; int I2S_state = 0; +static int raw_start_flag = 0; +static int mute_raw_data_size = 0; +static audio_format_t last_aformat = AUDIO_FORMAT_AC3; +//static int last_raw_flag = 0; +static int RawAudioTrackRelease(void); +static int RawAudioTrackInit(audio_format_t aformat,int sr); +static int amsysfs_set_sysfs_int(const char *path, int val) { + int fd; + int bytes; + char bcmd[16]; + fd = open(path, O_CREAT | O_RDWR | O_TRUNC, 0644); + if (fd >= 0) { + sprintf(bcmd, "%d", val); + bytes = write(fd, bcmd, strlen(bcmd)); + close(fd); + return 0; + } else { + ALOGE("unable to open file %s,err: %s", path, strerror(errno)); + } + return -1; +} +int amsysfs_get_sysfs_int(const char *path) { + int fd; + int val = 0; + char bcmd[16]; + fd = open(path, O_RDONLY); + if (fd >= 0) { + read(fd, bcmd, sizeof(bcmd)); + val = strtol(bcmd, NULL, 10); + close(fd); + }else { + ALOGE("unable to open file %s,err: %s", path, strerror(errno)); + } + return val; +} +static void RawAudioTrackCallback(int event, void* user, void *info) { + AudioTrack::Buffer *buffer = static_cast<AudioTrack::Buffer *>(info); + int bytes_raw = 0; + if (event != AudioTrack::EVENT_MORE_DATA) { + ALOGD("%s, audio track envent = %d!\n", __FUNCTION__, event); + return; + } + if (buffer == NULL || buffer->size == 0) { + return; + } + bytes_raw = buffer_read(&DD_out_buffer,(char *) buffer->raw, + buffer->size); + //ALOGI("raw read got %d\n",bytes_raw); + if ( bytes_raw > 0) { + buffer->size = bytes_raw; + } + else + buffer->size = 0; + if (buffer->size > 0 && mute_raw_data_size < 32*1024) { + memset((char *)(buffer->i16),0,buffer->size); + mute_raw_data_size += buffer->size; + } + return; +} static void AudioTrackCallback(int event, void* user, void *info) { AudioTrack::Buffer *buffer = static_cast<AudioTrack::Buffer *>(info); @@ -43,17 +103,47 @@ static void AudioTrackCallback(int event, void* user, void *info) { if (buffer == NULL || buffer->size == 0) { return; } - int bytes = 0; - pthread_mutex_lock(&device_change_lock); - - if (GetOutputdevice() == 1) { +// code for raw data start + audio_format_t aformat = AUDIO_FORMAT_INVALID; + int user_raw_enable = amsysfs_get_sysfs_int("/sys/class/audiodsp/digital_raw"); + //ALOGI("afmat %x,spdif_audio_type %x\n",aformat,spdif_audio_type); + int ddp_passth = (user_raw_enable == 2)&&(spdif_audio_type == EAC3); + if (user_raw_enable) { + if (ddp_passth) { + aformat = AUDIO_FORMAT_E_AC3; + } + else if (spdif_audio_type == AC3 || spdif_audio_type == EAC3 ) { + aformat = AUDIO_FORMAT_AC3; + } + else if (spdif_audio_type == DTS) { + aformat = AUDIO_FORMAT_DTS; + } + if (aformat != last_aformat && aformat != AUDIO_FORMAT_INVALID) { + ALOGI("raw aformat changed from %x to %x\n",last_aformat,aformat); + RawAudioTrackRelease(); + if (RawAudioTrackInit(aformat,48000/*TODO*/)) { + ALOGE("RawAudioTrackInit failed\n"); + return; + } + } + } +// raw data end + if (GetOutputdevice() == 1) { // output PCM output when PCM data in +//raw data start + RawAudioTrackRelease(); +// raw data end bytes = buffer_read(&android_out_buffer, (char *) buffer->raw, buffer->size); if (bytes < 0) buffer->size = 0; } else if (GetOutputdevice() == 2) { +//raw data start + if (user_raw_enable == 0) { + RawAudioTrackRelease(); + } +// raw date end bytes = buffer_read(&DDP_out_buffer, (char *) buffer->raw, buffer->size); if (bytes < 0) @@ -68,20 +158,35 @@ static void AudioTrackCallback(int event, void* user, void *info) { memset(buffer->i16, 0, buffer->size); } } - pthread_mutex_unlock(&device_change_lock); I2S_state += 1; return; } - -static int AudioTrackRelease(void) { -#if ANDROID_PLATFORM_SDK_VERSION < 19 - if (glpTracker != NULL) { - glpTracker->stop(); - delete glpTracker; - glpTracker = NULL; +static int RawAudioTrackRelease(void) { + //raw here + if (glpTracker_raw != NULL ) { + if (raw_start_flag == 1) + glpTracker_raw->stop(); + raw_start_flag = 0; + glpTracker_raw = NULL; } -#else + if (gmpAudioTracker_raw != NULL ) { + gmpAudioTracker_raw.clear(); + ALOGI("RawAudioTrackRelease done\n"); + } + gmpAudioTracker_raw = NULL; + // raw end +#if 0 + if (last_raw_flag == 2) { + ALOGI("change back digital raw to 2 for hdmi pass through\n"); + amsysfs_set_sysfs_int("/sys/class/audiodsp/digital_raw",2); + last_raw_flag = 0; + } +#endif + last_aformat = AUDIO_FORMAT_INVALID; + return 0; +} +static int AudioTrackRelease(void) { if (glpTracker != NULL ) { glpTracker->stop(); glpTracker = NULL; @@ -90,10 +195,56 @@ static int AudioTrackRelease(void) { if (gmpAudioTracker != NULL ) { gmpAudioTracker.clear(); } -#endif + RawAudioTrackRelease(); return 0; } +static int RawAudioTrackInit(audio_format_t aformat,int sr) +{ + status_t Status; + int user_raw_enable = amsysfs_get_sysfs_int("/sys/class/audiodsp/digital_raw"); + int ddp_passth = (user_raw_enable == 2)&&(spdif_audio_type == EAC3); + int ret; + ALOGD("%s, entering...,aformat %x,sr %d\n", __FUNCTION__,aformat,sr); + //raw here + gmpAudioTracker_raw = new AudioTrack(); + if (gmpAudioTracker_raw == NULL) { + ALOGE("%s, new gmpAudioTracker_raw failed.\n", __FUNCTION__); + return -1; + } + glpTracker_raw = gmpAudioTracker_raw.get(); + Status = glpTracker_raw->set(AUDIO_STREAM_MUSIC, sr, aformat, + AUDIO_CHANNEL_OUT_STEREO, 0, AUDIO_OUTPUT_FLAG_DIRECT, + RawAudioTrackCallback/*NULL*/, NULL, 0, 0, false, 0); + if (Status != NO_ERROR) { + ALOGE("%s, AudioTrack raw set failed.\n", __FUNCTION__); + if (gmpAudioTracker_raw != NULL ) { + gmpAudioTracker_raw.clear(); + glpTracker_raw = NULL; + } + return -1; + } + Status = glpTracker_raw->initCheck(); + if (Status != NO_ERROR) { + ALOGE("%s, AudioTrack raw initCheck failed.\n", __FUNCTION__); + RawAudioTrackRelease(); + return -1; + } + //raw end +#if 0 + int digital_raw = amsysfs_get_sysfs_int("/sys/class/audiodsp/digital_raw"); + if (digital_raw == 2) { + ALOGI("change digital raw to 2 for spdif pass through\n"); + amsysfs_set_sysfs_int("/sys/class/audiodsp/digital_raw",1); + last_raw_flag = 2; + } +#endif + glpTracker_raw->start(); + ALOGI("RawAudioTrackInit done\n"); + last_aformat = aformat; + mute_raw_data_size = 0; + return 0; +} static int AudioTrackInit(void) { status_t Status; @@ -101,20 +252,13 @@ static int AudioTrackInit(void) { I2S_state = 0; -#if ANDROID_PLATFORM_SDK_VERSION < 19 - glpTracker = new AudioTrack(); - if (glpTracker == NULL) { - ALOGE("%s, new AudioTrack failed.\n", __FUNCTION__); - return -1; - } -#else gmpAudioTracker = new AudioTrack(); if (gmpAudioTracker == NULL) { ALOGE("%s, new AudioTrack failed.\n", __FUNCTION__); return -1; } glpTracker = gmpAudioTracker.get(); -#endif + Status = glpTracker->set(AUDIO_STREAM_MUSIC, 48000, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 0, AUDIO_OUTPUT_FLAG_NONE, @@ -122,15 +266,16 @@ static int AudioTrackInit(void) { if (Status != NO_ERROR) { ALOGE("%s, AudioTrack set failed.\n", __FUNCTION__); - - AudioTrackRelease(); + if (gmpAudioTracker != NULL ) { + gmpAudioTracker.clear(); + glpTracker = NULL; + } return -1; } Status = glpTracker->initCheck(); if (Status != NO_ERROR) { ALOGE("%s, AudioTrack initCheck failed.\n", __FUNCTION__); - AudioTrackRelease(); return -1; } @@ -140,14 +285,11 @@ static int AudioTrackInit(void) { Status = glpTracker->setVolume(1.0, 1.0); if (Status != NO_ERROR) { ALOGE("%s, AudioTrack setVolume failed.\n", __FUNCTION__); - AudioTrackRelease(); return -1; } - ALOGD("%s, exit...\n", __FUNCTION__); - - return 0; + return 0;//RawAudioTrackInit(AUDIO_FORMAT_AC3,48000); } int new_android_audiotrack(void) { @@ -155,6 +297,7 @@ int new_android_audiotrack(void) { } int release_android_audiotrack(void) { + amsysfs_set_sysfs_int("/sys/class/audiodsp/digital_codec",0); return AudioTrackRelease(); } diff --git a/libTVaudio/audio/android_out.h b/libTVaudio/audio/android_out.h index 9deef75..3fbc222 100644 --- a/libTVaudio/audio/android_out.h +++ b/libTVaudio/audio/android_out.h @@ -7,6 +7,8 @@ extern "C" { int new_android_audiotrack(void); int release_android_audiotrack(void); +int amsysfs_get_sysfs_int(const char *path); + #ifdef __cplusplus } diff --git a/libTVaudio/audio/audio_amaudio.cpp b/libTVaudio/audio/audio_amaudio.cpp index f4010aa..a3105d5 100644 --- a/libTVaudio/audio/audio_amaudio.cpp +++ b/libTVaudio/audio/audio_amaudio.cpp @@ -15,16 +15,28 @@ #include <cutils/log.h> #include <cutils/properties.h> - #include <tinyalsa/asoundlib.h> +#include <hardware/audio.h> +#include "audio_usb_check.h" #include "audio_effect_control.h" #include "../audio_amaudio.h" #define LOG_TAG "LibAudioCtl" +int amSetAudioDelay(int delay_ms) { + return set_audio_delay(delay_ms); +} + +int amGetAudioDelay(void) { + return get_audio_delay(); +} + int amAudioOpen(unsigned int sr, int input_device, int output_device) { - return aml_audio_open(sr, input_device, output_device); + int ret; + ret = aml_audio_open(sr, input_device, output_device); + ret |= set_audio_delay(60); + return ret; } int amAudioClose(void) { @@ -39,21 +51,12 @@ int amAudioSetInputSr(unsigned int sr, int input_device, int output_device) { return -1; } - ALOGD("%s, sr = %d\n", __FUNCTION__, sr); - tmpRet |= amAudioClose(); tmpRet |= amAudioOpen(sr, input_device, output_device); return tmpRet; } -int amAudioSetOutputSr(unsigned int sr, int output_device) { - ALOGD("%s, sr = %d\n", __FUNCTION__, sr); - ALOGE("%s, amAudio not support set output sample rate\n", __FUNCTION__); - - return 0; -} - int amAudioSetDumpDataFlag(int tmp_flag) { return SetDumpDataFlag(tmp_flag); } @@ -78,52 +81,36 @@ int amAudioSetRightGain(int gain) { return set_right_gain(gain); } -int amAudioSetAndroidVolumeEnable(int enable) { - return set_android_volume_enable(enable); -} - -int amAudioSetAndroidVolume(int left, int right) { - return set_android_volume(left, right); -} - -int amAudioSetEQGain(int gain_val_buf[], int buf_item_cnt) { - int i = 0; - int tmp_buf[6] = { 0, 0, 0, 0, 0, 0 }; - - if (buf_item_cnt > 5) { - buf_item_cnt = 5; - } +int amAudioSetEQGain(int gain_val_buf[], int buf_item_cnt __unused) { + int i = 0, ret = 0; + int tmp_buf[5] = { 0, 0, 0, 0, 0}; - for (i = 0; i < buf_item_cnt; i++) { + for (i = 0; i < 5; i++) { tmp_buf[i] = gain_val_buf[i]; } HPEQ_setParameter(tmp_buf[0], tmp_buf[1], tmp_buf[2], tmp_buf[3], tmp_buf[4]); - return 0; + char param[15]; + char parm_key[] = AUDIO_PARAMETER_STREAM_EQ; + sprintf(param, "%02d%02d%02d%02d%02d", tmp_buf[0]+10, tmp_buf[1]+10, + tmp_buf[2]+10, tmp_buf[3]+10, tmp_buf[4]+10); + + ret = set_parameters(param, parm_key); + //ALOGE("EQ param : %s\n", param); + return ret; } -int amAudioGetEQGain(int gain_val_buf[], int buf_item_cnt) { - int i = 0, tmp_cnt = 0; - int tmp_buf[6] = { 0, 0, 0, 0, 0, 0 }; +int amAudioGetEQGain(int gain_val_buf[], int buf_item_cnt __unused) { + int i = 0; + int tmp_buf[5] = { 0, 0, 0, 0, 0}; HPEQ_getParameter(tmp_buf); - tmp_cnt = buf_item_cnt; - - if (buf_item_cnt > 5) { - tmp_cnt = 5; + for (i = 0; i < 5; i++) { + gain_val_buf[i] = tmp_buf[i]; } - - for (i = 0; i < buf_item_cnt; i++) { - if (i < tmp_cnt) { - gain_val_buf[i] = tmp_buf[i]; - } else { - gain_val_buf[i] = 0; - } - } - return 0; } @@ -135,62 +122,94 @@ int amAudioGetEQEnable() { return 0; } -int amAudioSetDoubleOutput(int en_val, unsigned int sr, int input_device, - int output_device) { - return amAudioSetInputSr(sr, input_device, output_device); -} - -int amAudioSetOutputRecordEnable(int enable) { - return 0; //set_output_record_enable(enable); -} - #define CC_SET_TYPE_TRUBASS_SPEAKERSIZE (0) #define CC_SET_TYPE_TRUBASS_GAIN (1) #define CC_SET_TYPE_DIALOGCLARITY_GAIN (2) #define CC_SET_TYPE_DEFINITION_GAIN (3) #define CC_SET_TYPE_SURROUND_GAIN (4) -#define CC_SET_TYPE_MAX (CC_SET_TYPE_SURROUND_GAIN) +#define CC_SET_TYPE_MAX (5) -static int amAudioSetSRSParameter(int set_type, int gain_val) { - int tmp_buf[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - if (srs_getParameter(tmp_buf) < 0) { - ALOGE("%s, srs_getParameter error.\n", __FUNCTION__); - return -1; - } - if (set_type < 0 || set_type > CC_SET_TYPE_MAX) { - ALOGE("%s, not support param set type (%d).\n", __FUNCTION__, set_type); - return -1; - } +int srs_param_buf[5] = { 0, 0, 0, 0, 0}; +static int amAudioSetSRSParameter(int set_type, int gain_val) { + int ret = 0; + + srs_param_buf[set_type] = gain_val; + ret = srs_setParameter(srs_param_buf); - tmp_buf[set_type] = gain_val; + char param[20]; + char parm_key[] = AUDIO_PARAMETER_STREAM_SRS; - return srs_setParameter(tmp_buf); + sprintf(param, "%03d%03d%03d%03d%03d", srs_param_buf[0], + srs_param_buf[1], srs_param_buf[2], + srs_param_buf[3], srs_param_buf[4]); + ret = set_parameters(param, parm_key); + return ret; } int amAudioSetSRSGain(int input_gain, int output_gain) { int ret = 0; + ret = srs_set_gain(input_gain, output_gain); + + char param[10]; + char parm_key[] = AUDIO_PARAMETER_STREAM_SRS_GAIN; + sprintf(param, "%03d%03d", input_gain, output_gain); + ret = set_parameters(param, parm_key); + return ret; } + +#define CC_SET_SWITCH_SURROUND (0) +#define CC_SET_SWITCH_DIALOGCLARITY (1) +#define CC_SET_SWITCH_TRUBASS (2) +int srs_switch[3]= {0, 0, 0}; + int amAudioSetSRSSurroundSwitch(int switch_val) { - return srs_surround_enable(switch_val); + int ret = 0; + ret = srs_surround_enable(switch_val); + + srs_switch[CC_SET_SWITCH_SURROUND] = switch_val; + char param[10]; + char parm_key[] = AUDIO_PARAMETER_STREAM_SRS_SWITCH; + sprintf(param, "%02d%02d%02d", srs_switch[0], srs_switch[1], srs_switch[2]); + ret = set_parameters(param, parm_key); + + return ret; } -int amAudioSetSRSSurroundGain(int gain_val) { - return amAudioSetSRSParameter(CC_SET_TYPE_SURROUND_GAIN, gain_val); +int amAudioSetSRSDialogClaritySwitch(int switch_val) { + int ret = 0; + ret = srs_dialogclarity_enable(switch_val); + + srs_switch[CC_SET_SWITCH_DIALOGCLARITY] = switch_val; + char param[10]; + char parm_key[] = AUDIO_PARAMETER_STREAM_SRS_SWITCH; + sprintf(param, "%02d%02d%02d", srs_switch[0], srs_switch[1], srs_switch[2]); + ret = set_parameters(param, parm_key); + + return ret; } int amAudioSetSRSTrubassSwitch(int switch_val) { - return srs_truebass_enable(switch_val); + int ret = 0; + ret = srs_truebass_enable(switch_val); + + srs_switch[CC_SET_SWITCH_TRUBASS] = switch_val; + char param[10]; + char parm_key[] = AUDIO_PARAMETER_STREAM_SRS_SWITCH; + sprintf(param, "%02d%02d%02d", srs_switch[0], srs_switch[1], srs_switch[2]); + ret = set_parameters(param, parm_key); + + return ret; } -int amAudioSetSRSTrubassGain(int gain_val) { - return amAudioSetSRSParameter(CC_SET_TYPE_TRUBASS_GAIN, gain_val); +int amAudioSetSRSSurroundGain(int gain_val) { + return amAudioSetSRSParameter(CC_SET_TYPE_SURROUND_GAIN, gain_val); } -int amAudioSetSRSDialogClaritySwitch(int switch_val) { - return srs_dialogclarity_enable(switch_val); +int amAudioSetSRSTrubassGain(int gain_val) { + return amAudioSetSRSParameter(CC_SET_TYPE_TRUBASS_GAIN, gain_val); } int amAudioSetSRSDialogClarityGain(int gain_val) { @@ -202,12 +221,6 @@ int amAudioSetSRSDefinitionGain(int gain_val) { } int amAudioSetSRSTrubassSpeakerSize(int tmp_val) { - int tmp_buf[8] = { 40, 60, 100, 150, 200, 250, 300, 400 }; - int gain_val = 40; - - if (tmp_val >= 0 && tmp_val < (int) sizeof(tmp_buf)) { - gain_val = tmp_buf[tmp_val]; - } - - return amAudioSetSRSParameter(CC_SET_TYPE_TRUBASS_SPEAKERSIZE, gain_val); + return amAudioSetSRSParameter(CC_SET_TYPE_TRUBASS_SPEAKERSIZE, tmp_val); } + diff --git a/libTVaudio/audio/audio_effect_control.c b/libTVaudio/audio/audio_effect_control.c index 02247b1..c58d558 100644 --- a/libTVaudio/audio/audio_effect_control.c +++ b/libTVaudio/audio/audio_effect_control.c @@ -12,7 +12,7 @@ #include "aml_audio.h" #include "audio_effect_control.h" -#define LOG_TAG "audioeffect" +#define LOG_TAG "effect_ctl" //------------------------------------EQ control------------------------------------------------ int (*EQ_process)(short *in, short *out, int framecount); @@ -189,7 +189,7 @@ int (*SRS_TRUEBASS_ENABLE)(int value); int (*SRS_DIALOGCLARITY_ENABLE)(int value); int (*SRS_SURROUND_ENABLE)(int value); int (*SRS_process)(short *in, short *out, int framecount); - +int (*SRS_set_gain)(float input_gain, float output_gain); static void *gSRSLibHandler = NULL; int unload_SRS_lib(void) { @@ -205,7 +205,7 @@ int unload_SRS_lib(void) { SRS_TRUEBASS_ENABLE = NULL; SRS_DIALOGCLARITY_ENABLE = NULL; SRS_SURROUND_ENABLE = NULL; - + SRS_set_gain = NULL; if (gSRSLibHandler != NULL) { dlclose(gSRSLibHandler); gSRSLibHandler = NULL; @@ -273,10 +273,13 @@ int load_SRS_lib(void) { ALOGE("%s, fail find fun SRS_SURROUND_ENABLE_api\n", __FUNCTION__); goto Error; } - + SRS_set_gain = (int (*)(float,float))dlsym(gSRSLibHandler, "SRS_set_gain_api"); + if (SRS_set_gain == NULL) { + ALOGE("%s, fail find fun SRS_set_gain_api\n", __FUNCTION__); + goto Error; + } return 0; - - Error: // +Error: unload_SRS_lib(); return -1; } @@ -327,9 +330,9 @@ int srs_setParameter(int SRS_user_config[]) { truebass_spker_size = SRS_user_config[0]; truebass_gain = (float) SRS_user_config[1] / (float) 100; - dialogclarity_gain = (float) SRS_user_config[1] / (float) 100; - definition_gain = (float) SRS_user_config[1] / (float) 100; - surround_gain = (float) SRS_user_config[1] / (float) 100; + dialogclarity_gain = (float) SRS_user_config[2] / (float) 100; + definition_gain = (float) SRS_user_config[3] / (float) 100; + surround_gain = (float) SRS_user_config[4] / (float) 100; ret = (*SRS_setParameter)(truebass_spker_size, truebass_gain, dialogclarity_gain, definition_gain, surround_gain); @@ -367,6 +370,16 @@ int srs_getParameter(int SRS_user_config[]) { return 0; } +int srs_set_gain(int input_gain, int output_gain) { + int ret = 0; + if (SRS_set_gain == NULL) { + ALOGE("%s, pls load lib first.\n", __FUNCTION__); + return -1; + } + ret = (*SRS_set_gain)((float)input_gain/(float)100, (float)output_gain/(float)100); + return ret; +} + int srs_truebass_enable(int enable) { int ret = 0; @@ -409,7 +422,7 @@ int srs_surround_enable(int enable) { int srs_process(short *in, short *out, int framecount) { int output_framecount = 0; - //In SRS prosess, framecount must be aligned by 64. + //In SRS prosess, framecount must be aligned by 64. int input_framecount = framecount >> 6 << 6; if (SRS_process == NULL) { diff --git a/libTVaudio/audio/audio_effect_control.h b/libTVaudio/audio/audio_effect_control.h index 4e2cc7c..ad7984d 100644 --- a/libTVaudio/audio/audio_effect_control.h +++ b/libTVaudio/audio/audio_effect_control.h @@ -36,6 +36,7 @@ int srs_init(int sample_rate); int srs_release(void); int srs_setParameter(int SRS_user_config[]); int srs_getParameter(int SRS_user_config[]); +int srs_set_gain(int input_gain, int output_gain); int srs_truebass_enable(int enable); int srs_dialogclarity_enable(int enable); int srs_surround_enable(int enable); diff --git a/libTVaudio/audio/audio_usb_check.cpp b/libTVaudio/audio/audio_usb_check.cpp index 2cbcc28..705e59f 100644 --- a/libTVaudio/audio/audio_usb_check.cpp +++ b/libTVaudio/audio/audio_usb_check.cpp @@ -1,29 +1,143 @@ -/* - audio_usb_check.cpp - check usb audio device. - */ - #include <stdio.h> #include <string.h> #include <stdlib.h> #include <errno.h> #include <cutils/log.h> +#include <pthread.h> +#include <sys/prctl.h> #include <media/AudioSystem.h> +#include <media/AudioParameter.h> +#include <cutils/properties.h> #include "audio_usb_check.h" +#include "aml_audio.h" -#define LOG_TAG "audio_usb_check" +#define LOG_TAG "aml_audio" namespace android { -extern "C" int GetUsbAudioCheckFlag() { - int device = (int)AudioSystem::getDevicesForStream(AUDIO_STREAM_MUSIC); - return device; +unsigned int deviceID = 0; +extern "C" unsigned int GetUsbAudioCheckFlag(void) { + return deviceID; +} + +static float last_vol = 1.0; +extern "C" float get_android_stream_volume() { + return last_vol; +} + +extern "C" int set_parameters(char parameters[], char parm_key[]) { + + AudioParameter param = AudioParameter(); + String8 value = String8(parameters); + String8 key = String8(parm_key); + param.add(key, value); + + String8 keyValuePairs = param.toString(); + //ALOGI("%s\n", param.toString().string()); + + audio_io_handle_t handle = -1; + handle = AudioSystem::getOutput(AUDIO_STREAM_MUSIC, + 48000, + AUDIO_FORMAT_PCM_16_BIT, + AUDIO_CHANNEL_OUT_STEREO, + AUDIO_OUTPUT_FLAG_PRIMARY + ); + if (handle > 0) { + if (AudioSystem::setParameters(handle, keyValuePairs) != NO_ERROR) { + ALOGI("Set audio Parameters failed!\n"); + return -1; + } + } else { + ALOGI("get output handle failed\n"); + return -1; + } + param.remove(key); + return 0; +} + +static int GetDeviceID(void) { + deviceID = AudioSystem::getDevicesForStream(AUDIO_STREAM_MUSIC); + return 0; +} + +static int GetStreamVolume(void) { + float vol = last_vol; + unsigned int sr = 0; + AudioSystem::getOutputSamplingRate(&sr, AUDIO_STREAM_MUSIC); + if (sr > 0) { + audio_io_handle_t handle = -1; + handle = AudioSystem::getOutput(AUDIO_STREAM_MUSIC, + 48000, + AUDIO_FORMAT_PCM_16_BIT, + AUDIO_CHANNEL_OUT_STEREO, + AUDIO_OUTPUT_FLAG_PRIMARY + ); + if (handle > 0) { + if (AudioSystem::getStreamVolume(AUDIO_STREAM_MUSIC,&vol,handle) == NO_ERROR) { + last_vol = vol; + } else + ALOGI("get stream volume failed\n"); + }else + ALOGI("get output handle failed\n"); + } + return 0; +} + +static int SetAudioDelay(void) { + char value[PROPERTY_VALUE_MAX]; + if (property_get("media.TV.audio.delay", value, NULL) > 0) { + int delay = atoi(value); + if (delay > 0 && get_audio_delay() != delay) + set_audio_delay(delay); + } + return 0; +} + +} + +static int running_flag = 0; +void* android_check_threadloop(void *data __unused) { + running_flag = 1; + //ALOGI("Start thread loop for android check!\n"); + while (running_flag) { + android::GetStreamVolume(); + android::GetDeviceID(); + android::SetAudioDelay(); + usleep(100*1000); + } + //ALOGI("Exit thread loop for android check!\n"); + return ((void *) 0); } +extern "C" int creat_pthread_for_android_check + (pthread_t *android_check_ThreadID) { + pthread_attr_t attr; + struct sched_param param; + int ret; + + pthread_attr_init(&attr); + pthread_attr_setschedpolicy(&attr, SCHED_RR); + //param.sched_priority = sched_get_priority_max(SCHED_RR); + param.sched_priority = 50; + pthread_attr_setschedparam(&attr, ¶m); + ret = pthread_create(android_check_ThreadID, &attr, + &android_check_threadloop, NULL); + pthread_attr_destroy(&attr); + if (ret != 0) { + ALOGE("%s, Create thread fail!\n", __FUNCTION__); + return -1; + } + prctl(PR_SET_NAME, (unsigned long)"aml_TV_check"); + //ALOGI("Creat thread ID: %u!\n", *android_check_ThreadID); + return 0; } -int createMonitorUsbHostBusThread() { +extern "C" int exit_pthread_for_android_check + (pthread_t android_check_ThreadID) { + running_flag = 0; + //ALOGI("Exit thread ID: %u!\n", android_check_ThreadID); + pthread_join(android_check_ThreadID, NULL); return 0; } diff --git a/libTVaudio/audio/audio_usb_check.h b/libTVaudio/audio/audio_usb_check.h index 8116c13..936b029 100644 --- a/libTVaudio/audio/audio_usb_check.h +++ b/libTVaudio/audio/audio_usb_check.h @@ -1,15 +1,17 @@ #ifndef __TV_USB_AUDIO_CHECK_H__ #define __TV_USB_AUDIO_CHECK_H__ -#define CC_USB_AUDIO_PLAYBACK_BIT_IND (0) -#define CC_USB_AUDIO_CAPTURE_BIT_IND (1) - #ifdef __cplusplus extern "C" { #endif -int createMonitorUsbHostBusThread(); -int GetUsbAudioCheckFlag(); +unsigned int GetUsbAudioCheckFlag(void); +float get_android_stream_volume(void); +int set_parameters(char parameters[], char parm_key[]); +int creat_pthread_for_android_check + (pthread_t *android_check_ThreadID); +int exit_pthread_for_android_check + (pthread_t android_check_ThreadID); #ifdef __cplusplus } diff --git a/libTVaudio/audio_amaudio.h b/libTVaudio/audio_amaudio.h index 2e2938e..e3262b1 100644 --- a/libTVaudio/audio_amaudio.h +++ b/libTVaudio/audio_amaudio.h @@ -2,24 +2,16 @@ #define __TV_AUDIO_AMAUDIO_H__ #include "audio/aml_audio.h" -#include "audio/audio_usb_check.h" +int amSetAudioDelay(int delay_ms); +int amGetAudioDelay(void); int amAudioOpen(unsigned int sr, int input_device, int output_device); int amAudioClose(void); int amAudioSetInputSr(unsigned int sr, int input_device, int output_device); -int amAudioSetOutputSr(unsigned int sr, int output_device); -int amAudioSetDumpDataFlag(int tmp_flag); -int amAudioGetDumpDataFlag(); - int amAudioSetOutputMode(int mode); int amAudioSetMusicGain(int gain); int amAudioSetLeftGain(int gain); int amAudioSetRightGain(int gain); -int amAudioSetAndroidVolumeEnable(int enable); -int amAudioSetAndroidVolume(int left, int right); -int amAudioSetOutputRecordEnable(int enable); -int amAudioSetDoubleOutput(int en_val, unsigned int sr, int input_device, - int output_device); int amAudioSetEQGain(int gain_val_buf[], int buf_item_cnt); int amAudioGetEQGain(int gain_val_buf[], int buf_item_cnt); @@ -36,4 +28,7 @@ int amAudioSetSRSDefinitionGain(int gain_val); int amAudioSetSRSTrubassSpeakerSize(int tmp_val); int amAudioSetSRSGain(int input_gain, int output_gain); +int amAudioSetDumpDataFlag(int tmp_flag); +int amAudioGetDumpDataFlag(); + #endif //__TV_AUDIO_AMAUDIO_H__ |