From 30014c35d02c812ff3ec2fbbcf61905cd7500281 Mon Sep 17 00:00:00 2001 From: Shuai Li Date: Thu, 12 Jan 2017 06:17:53 +0000 Subject: PD#138361: audio: enable HDMI dynamic profile and HWSYNC property - fix profile get parameter bugs:"sup_formats=" - remove hwsync params in 'dev' - fix a/v sync issue after seek - fix compiling warnings - fix 6 CTS fails on AudioTrackSurroundTest Change-Id: Id00a15c0f17903e0f6530cf3b8a5a8c464f01708 --- diff --git a/Android.mk b/Android.mk index 1337272..12cd68c 100644 --- a/Android.mk +++ b/Android.mk @@ -31,7 +31,8 @@ ifeq ($(strip $(BOARD_ALSA_AUDIO)),tiny) libTVaudio/audio/audio_effect_control.c \ audio_hw_utils.c \ audio_hwsync.c \ - //spdifenc_wrap.cpp + spdifenc_wrap.cpp \ + audio_hw_profile.c LOCAL_C_INCLUDES += \ external/tinyalsa/include \ system/media/audio_utils/include \ diff --git a/audio_hw.c b/audio_hw.c index c666627..17f2459 100644 --- a/audio_hw.c +++ b/audio_hw.c @@ -15,7 +15,7 @@ */ #define LOG_TAG "audio_hw_primary" -//#define LOG_NALOGV 0 +//#define LOG_NDEBUG 0 //#define LOG_NALOGV_FUNCTION #ifdef LOG_NALOGV_FUNCTION #define LOGFUNC(...) ((void)0) @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -49,12 +50,8 @@ #include "libTVaudio/audio/audio_effect_control.h" #include "audio_hw.h" #include "audio_hw_utils.h" +#include "audio_hw_profile.h" #include "spdifenc_wrap.h" -//extern int spdifenc_write(const void *buffer, size_t numBytes); -//extern uint64_t spdifenc_get_total(); -extern void aml_audio_hwsync_clear_status(struct aml_stream_out *out); -extern int aml_audio_hwsync_find_frame(struct aml_stream_out *out, - const void *in_buffer, size_t in_bytes, uint64_t *cur_pts, int *outsize); /* ALSA cards for AML */ #define CARD_AMLOGIC_BOARD 0 @@ -90,14 +87,6 @@ static unsigned CAPTURE_PERIOD_SIZE = DEFAULT_CAPTURE_PERIOD_SIZE; #define VX_NB_SAMPLING_RATE 8000 #define MIXER_XML_PATH "/system/etc/mixer_paths.xml" -#define TSYNC_FIRSTAPTS "/sys/class/tsync/firstapts" -#define TSYNC_PCRSCR "/sys/class/tsync/pts_pcrscr" -#define TSYNC_EVENT "/sys/class/tsync/event" -#define TSYNC_APTS "/sys/class/tsync/pts_audio" -#define SYSTIME_CORRECTION_THRESHOLD (90000*10/100) -#define APTS_DISCONTINUE_THRESHOLD_MIN (90000/1000*100) -#define APTS_DISCONTINUE_THRESHOLD_MAX (5*90000) - static const struct pcm_config pcm_config_out = { .channels = 2, .rate = MM_FULL_POWER_SAMPLING_RATE, @@ -130,10 +119,6 @@ static const struct pcm_config pcm_config_bt = { .format = PCM_FORMAT_S16_LE, }; -#define HW_SYNC_STATE_HEADER 0 -#define HW_SYNC_STATE_BODY 1 -#define HW_SYNC_STATE_RESYNC 2 - static void select_output_device(struct aml_audio_device *adev); static void select_input_device(struct aml_audio_device *adev); static void select_devices(struct aml_audio_device *adev); @@ -245,35 +230,6 @@ static int aml_hal_mixer_read(struct aml_hal_mixer *mixer, void *r_buf, uint siz return size; } // aml audio hal mixer code end -#if 0 -static inline bool hwsync_header_valid(uint8_t *header) -{ - return (header[0] == 0x55) && - (header[1] == 0x55) && - (header[2] == 0x00) && - (header[3] == 0x01); -} - -static inline uint64_t hwsync_header_get_pts(uint8_t *header) -{ - return (((uint64_t)header[8]) << 56) | - (((uint64_t)header[9]) << 48) | - (((uint64_t)header[10]) << 40) | - (((uint64_t)header[11]) << 32) | - (((uint64_t)header[12]) << 24) | - (((uint64_t)header[13]) << 16) | - (((uint64_t)header[14]) << 8) | - ((uint64_t)header[15]); -} - -static inline uint32_t hwsync_header_get_size(uint8_t *header) -{ - return (((uint32_t)header[4]) << 24) | - (((uint32_t)header[5]) << 16) | - (((uint32_t)header[6]) << 8) | - ((uint32_t)header[7]); -} -#endif static void select_devices(struct aml_audio_device *adev) { @@ -344,113 +300,6 @@ static void select_mode(struct aml_audio_device *adev) return; } -static int get_aml_card(void) -{ - int card = -1, err = 0; - int fd = -1; - unsigned fileSize = 512; - char *read_buf = NULL, *pd = NULL; - static const char *const SOUND_CARDS_PATH = "/proc/asound/cards"; - fd = open(SOUND_CARDS_PATH, O_RDONLY); - if (fd < 0) { - ALOGE("ERROR: failed to open config file %s error: %d\n", SOUND_CARDS_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_CARDS_PATH, errno); - close(fd); - return -EINVAL; - } - pd = strstr(read_buf, "AML"); - card = *(pd - 3) - '0'; - -OUT: - free(read_buf); - close(fd); - return card; -} - -static int get_pcm_bt_port(void) -{ - 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; - } - pd = strstr(read_buf, "pcm2bt-pcm"); - port = *(pd + 11) - '0'; - -OUT: - free(read_buf); - close(fd); - return port; -} - -static int get_spdif_port() -{ - 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; - } - pd = strstr(read_buf, "SPDIF"); - port = *(pd - 3) - '0'; - -OUT: - free(read_buf); - close(fd); - return port; -} /* must be called with hw device and output stream mutexes locked */ static int start_output_stream(struct aml_stream_out *out) { @@ -662,7 +511,6 @@ static int start_output_stream_direct(struct aml_stream_out *out) out->spdif_enc_init_frame_write_sum = out->frame_write_sum; } out->codec_type = codec_type; - out->bytes_write_total = 0; if (out->hw_sync_mode == 1) { LOGFUNC("start_output_stream with hw sync enable %p\n", out); @@ -786,7 +634,7 @@ static int get_playback_delay(struct aml_stream_out *out, struct echo_reference_buffer *buffer) { - size_t kernel_frames; + unsigned int kernel_frames; int status; status = pcm_get_htimestamp(out->pcm, &kernel_frames, &buffer->time_stamp); if (status < 0) { @@ -828,7 +676,8 @@ static size_t out_get_buffer_size(const struct audio_stream *stream) { struct aml_stream_out *out = (struct aml_stream_out *)stream; - //LOGFUNC("%s(out->config.rate=%d)", __FUNCTION__, out->config.rate); + ALOGV("%s(out->config.rate=%d, format %x)", __FUNCTION__, + out->config.rate, out->hal_format); /* take resampling into account and return the closest majoring * multiple of 16 frames, as audioflinger expects audio buffers to @@ -841,14 +690,14 @@ static size_t out_get_buffer_size(const struct audio_stream *stream) if (out->flags & AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO) { size = 4 * PERIOD_SIZE * PLAYBACK_PERIOD_COUNT; } else { - size = PLAYBACK_PERIOD_COUNT * PERIOD_SIZE / 2; + size = PERIOD_SIZE; } break; case AUDIO_FORMAT_E_AC3: if (out->flags & AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO) { size = 16 * PERIOD_SIZE * PLAYBACK_PERIOD_COUNT; } else { - size = PERIOD_SIZE; //2*PLAYBACK_PERIOD_COUNT*PERIOD_SIZE; + size = PLAYBACK_PERIOD_COUNT*PERIOD_SIZE; //PERIOD_SIZE; } break; case AUDIO_FORMAT_DTS_HD: @@ -985,6 +834,7 @@ static int do_output_standby_direct(struct aml_stream_out *out) pcm_close(out->pcm); out->pcm = NULL; } + out->pause_status = false; set_codec_type(TYPE_PCM); /* clear the hdmitx channel config to default */ if (out->multich == 6) { @@ -1024,6 +874,7 @@ static int out_standby_direct(struct audio_stream *stream) pcm_close(out->pcm); out->pcm = NULL; } + out->pause_status = false; set_codec_type(TYPE_PCM); /* clear the hdmitx channel config to default */ if (out->multich == 6) { @@ -1066,6 +917,10 @@ out_flush(struct audio_stream_out *stream) standy_func(out); out->frame_write_sum = 0; out->last_frames_postion = 0; + out->spdif_enc_init_frame_write_sum = 0; + out->frame_skip_sum = 0; + out->skip_frame = 3; + exit: pthread_mutex_unlock(&adev->lock); pthread_mutex_unlock(&out->lock); @@ -1238,10 +1093,11 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) if (ret >= 0) { int hw_sync_id = atoi(value); unsigned char sync_enable = (hw_sync_id == 12345678) ? 1 : 0; + audio_hwsync_t *hw_sync = &out->hwsync; ALOGI("(%p)set hw_sync_id %d,%s hw sync mode\n", out, hw_sync_id, sync_enable ? "enable" : "disable"); out->hw_sync_mode = sync_enable; - out->first_apts_flag = false; + hw_sync->first_apts_flag = false; pthread_mutex_lock(&adev->lock); pthread_mutex_lock(&out->lock); out->frame_write_sum = 0; @@ -1265,26 +1121,82 @@ exit: return ret; } -static char * out_get_parameters(const struct audio_stream *stream __unused, const char *keys __unused) +static char *out_get_parameters(const struct audio_stream *stream, const char *keys) { + char *cap = NULL; + char *para = NULL; + struct aml_stream_out *out = (struct aml_stream_out *) stream; + struct aml_audio_device *adev = out->dev; + ALOGI("out_get_parameters %s,out %p\n", keys, out); + if (strstr(keys, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) { + if (out->out_device & AUDIO_DEVICE_OUT_HDMI_ARC) { + cap = (char *)get_hdmi_arc_cap(adev->hdmi_arc_ad, HDMI_ARC_MAX_FORMAT, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES); + } else { + cap = (char *)get_hdmi_sink_cap(AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES); + } + if (cap) { + para = strdup(cap); + free(cap); + } else { + para = strdup(""); + } + ALOGI("%s\n", para); + return para; + } else if (strstr(keys, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) { + if (out->out_device & AUDIO_DEVICE_OUT_HDMI_ARC) { + cap = (char *)get_hdmi_arc_cap(adev->hdmi_arc_ad, HDMI_ARC_MAX_FORMAT, AUDIO_PARAMETER_STREAM_SUP_CHANNELS); + } else { + cap = (char *)get_hdmi_sink_cap(AUDIO_PARAMETER_STREAM_SUP_CHANNELS); + } + if (cap) { + para = strdup(cap); + free(cap); + } else { + para = strdup(""); + } + ALOGI("%s\n", para); + return para; + } else if (strstr(keys, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) { + if (out->out_device & AUDIO_DEVICE_OUT_HDMI_ARC) { + cap = (char *)get_hdmi_arc_cap(adev->hdmi_arc_ad, HDMI_ARC_MAX_FORMAT, AUDIO_PARAMETER_STREAM_SUP_FORMATS); + } else { + cap = (char *)get_hdmi_sink_cap(AUDIO_PARAMETER_STREAM_SUP_FORMATS); + } + if (cap) { + para = strdup(cap); + free(cap); + } else { + para = strdup(""); + } + ALOGI("%s\n", para); + return para; + } return strdup(""); } -static uint32_t out_get_latency(const struct audio_stream_out *stream) +static uint32_t out_get_latency_frames(const struct audio_stream_out *stream) { const struct aml_stream_out *out = (const struct aml_stream_out *)stream; - uint32_t whole_latency; - int ret = 0; snd_pcm_sframes_t frames = 0; - whole_latency = (out->config.period_size * out->config.period_count * 1000) / out->config.rate; + uint32_t whole_latency_frames; + int ret = 0; + + whole_latency_frames = out->config.period_size * out->config.period_count; if (!out->pcm || !pcm_is_ready(out->pcm)) { - return whole_latency; + return whole_latency_frames; } ret = pcm_ioctl(out->pcm, SNDRV_PCM_IOCTL_DELAY, &frames); if (ret < 0) { - return whole_latency; + return whole_latency_frames; } - return (frames * 1000) / out->config.rate/* (out->pcm->config.rate)*/; + return frames; +} + +static uint32_t out_get_latency(const struct audio_stream_out *stream) +{ + const struct aml_stream_out *out = (const struct aml_stream_out *)stream; + snd_pcm_sframes_t frames = out_get_latency_frames(stream); + return (frames * 1000) / out->config.rate; } static int out_set_volume(struct audio_stream_out *stream, float left, float right) @@ -1415,6 +1327,7 @@ static ssize_t out_write_legacy(struct audio_stream_out *stream, const void* buf uint32_t latency_frames = 0; int need_mix = 0; short *mix_buf = NULL; + audio_hwsync_t *hw_sync = &out->hwsync; unsigned char enable_dump = getprop_bool("media.audiohal.outdump"); // limit HAL mixer buffer level within 200ms while ((adev->hwsync_output != NULL && adev->hwsync_output != out) && @@ -1478,9 +1391,9 @@ static ssize_t out_write_legacy(struct audio_stream_out *stream, const void* buf } if ((out->standby) && (out->hw_sync_mode == 1)) { // todo: check timestamp header PTS discontinue for new sync point after seek - out->first_apts_flag = false; - out->hw_sync_state = HW_SYNC_STATE_HEADER; - out->hw_sync_header_cnt = 0; + hw_sync->first_apts_flag = false; + hw_sync->hw_sync_state = HW_SYNC_STATE_HEADER; + hw_sync->hw_sync_header_cnt = 0; } #if 1 @@ -1497,20 +1410,20 @@ static ssize_t out_write_legacy(struct audio_stream_out *stream, const void* buf char buf[64] = {0}; unsigned char *header; - if (out->hw_sync_state == HW_SYNC_STATE_RESYNC) { + if (hw_sync->hw_sync_state == HW_SYNC_STATE_RESYNC) { uint i = 0; uint8_t *p = (uint8_t *)buffer; while (i < bytes) { if (hwsync_header_valid(p)) { ALOGI("HWSYNC resync.%p", out); - out->hw_sync_state = HW_SYNC_STATE_HEADER; - out->hw_sync_header_cnt = 0; - out->first_apts_flag = false; + hw_sync->hw_sync_state = HW_SYNC_STATE_HEADER; + hw_sync->hw_sync_header_cnt = 0; + hw_sync->first_apts_flag = false; bytes -= i; - buffer += i; + p += i; in_frames = bytes / frame_size; - ALOGI("in_frames = %d", in_frames); - in_buffer = (int16_t *)buffer; + ALOGI("in_frames = %zu", in_frames); + in_buffer = (int16_t *)p; break; } else { i += 4; @@ -1518,7 +1431,7 @@ static ssize_t out_write_legacy(struct audio_stream_out *stream, const void* buf } } - if (out->hw_sync_state == HW_SYNC_STATE_RESYNC) { + if (hw_sync->hw_sync_state == HW_SYNC_STATE_RESYNC) { ALOGI("Keep searching for HWSYNC header.%p", out); pthread_mutex_unlock(&adev->lock); goto exit; @@ -1622,62 +1535,64 @@ if (!(adev->out_device & AUDIO_DEVICE_OUT_ALL_SCO)) { } else { if (out->hw_sync_mode) { - int remain = out_frames * frame_size; - uint8_t *p = buffer; + size_t remain = out_frames * frame_size; + uint8_t *p = (uint8_t *)buffer; //ALOGI(" --- out_write %d, cache cnt = %d, body = %d, hw_sync_state = %d", out_frames * frame_size, out->body_align_cnt, out->hw_sync_body_cnt, out->hw_sync_state); while (remain > 0) { - if (out->hw_sync_state == HW_SYNC_STATE_HEADER) { + if (hw_sync->hw_sync_state == HW_SYNC_STATE_HEADER) { //ALOGI("Add to header buffer [%d], 0x%x", out->hw_sync_header_cnt, *p); - out->hw_sync_header[out->hw_sync_header_cnt++] = *p++; + out->hwsync.hw_sync_header[out->hwsync.hw_sync_header_cnt++] = *p++; remain--; - if (out->hw_sync_header_cnt == 16) { - int64_t pts; - if (!hwsync_header_valid(&out->hw_sync_header[0])) { + if (hw_sync->hw_sync_header_cnt == 16) { + uint64_t pts; + if (!hwsync_header_valid(&hw_sync->hw_sync_header[0])) { ALOGE("hwsync header out of sync! Resync."); - out->hw_sync_state = HW_SYNC_STATE_RESYNC; + hw_sync->hw_sync_state = HW_SYNC_STATE_RESYNC; break; } - out->hw_sync_state = HW_SYNC_STATE_BODY; - out->hw_sync_body_cnt = hwsync_header_get_size(&out->hw_sync_header[0]); - out->body_align_cnt = 0; - pts = hwsync_header_get_pts(&out->hw_sync_header[0]); + hw_sync->hw_sync_state = HW_SYNC_STATE_BODY; + hw_sync->hw_sync_body_cnt = hwsync_header_get_size(&hw_sync->hw_sync_header[0]); + hw_sync->body_align_cnt = 0; + pts = hwsync_header_get_pts(&hw_sync->hw_sync_header[0]); pts = pts * 90 / 1000000; #if 1 char buf[64] = {0}; - if (out->first_apts_flag == false) { + if (hw_sync->first_apts_flag == false) { uint32_t apts_cal; - ALOGI("HW SYNC new first APTS %lld,body size %d", pts, out->hw_sync_body_cnt); - out->first_apts_flag = true; - out->first_apts = pts; + ALOGI("HW SYNC new first APTS %zd,body size %zu", pts, hw_sync->hw_sync_body_cnt); + hw_sync->first_apts_flag = true; + hw_sync->first_apts = pts; out->frame_write_sum = 0; - out->last_apts_from_header = pts; - sprintf(buf, "AUDIO_START:0x%llx", pts & 0xffffffff); + hw_sync->last_apts_from_header = pts; + sprintf(buf, "AUDIO_START:0x%"PRIx64"", pts & 0xffffffff); ALOGI("tsync -> %s", buf); if (sysfs_set_sysfs_str(TSYNC_EVENT, buf) == -1) { ALOGE("set AUDIO_START failed \n"); } } else { - int64_t apts; - uint32_t latency = out_get_latency(out) * 90; + uint64_t apts; + uint32_t latency = out_get_latency(stream) * 90; apts = (uint64_t)out->frame_write_sum * 90000 / DEFAULT_OUT_SAMPLING_RATE; - apts += out->first_apts; + apts += hw_sync->first_apts; // check PTS discontinue, which may happen when audio track switching // discontinue means PTS calculated based on first_apts and frame_write_sum // does not match the timestamp of next audio samples - apts -= latency; - if (apts < 0) { + if (apts > latency) { + apts -= latency; + } else { apts = 0; } + // here we use acutal audio frame gap,not use the differece of caculated current apts with the current frame pts, //as there is a offset of audio latency from alsa. // handle audio gap 0.5~5 s - unsigned two_frame_gap = (unsigned)llabs(out->last_apts_from_header - pts); + uint64_t two_frame_gap = pts_abs(hw_sync->last_apts_from_header, pts); if (two_frame_gap > APTS_DISCONTINUE_THRESHOLD_MIN && two_frame_gap < APTS_DISCONTINUE_THRESHOLD_MAX) { /* if (abs(pts -apts) > APTS_DISCONTINUE_THRESHOLD_MIN && abs(pts -apts) < APTS_DISCONTINUE_THRESHOLD_MAX) { */ - ALOGI("HW sync PTS discontinue, 0x%llx->0x%llx(from header) diff %d,last apts %llx(from header)", - apts, pts, two_frame_gap, out->last_apts_from_header); + ALOGI("HW sync PTS discontinue, 0x%"PRIx64"->0x%"PRIx64"(from header) diff %"PRIx64",last apts %"PRIx64"(from header)", + apts, pts, two_frame_gap, hw_sync->last_apts_from_header); //here handle the audio gap and insert zero to the alsa uint insert_size = 0; uint insert_size_total = 0; @@ -1685,7 +1600,7 @@ if (!(adev->out_device & AUDIO_DEVICE_OUT_ALL_SCO)) { insert_size = two_frame_gap/*abs(pts -apts) */ / 90 * 48 * 4; insert_size = insert_size & (~63); insert_size_total = insert_size; - ALOGI("audio gap %d ms ,need insert pcm size %d\n", two_frame_gap/*abs(pts -apts) */ / 90, insert_size); + ALOGI("audio gap %"PRIx64" ms ,need insert pcm size %d\n", two_frame_gap/*abs(pts -apts) */ / 90, insert_size); char *insert_buf = (char*)malloc(8192); if (insert_buf == NULL) { ALOGE("malloc size failed \n"); @@ -1755,7 +1670,7 @@ if (!(adev->out_device & AUDIO_DEVICE_OUT_ALL_SCO)) { // do nothing } else { sprintf(buf, "0x%x", apts_cal); - ALOGI("tsync -> reset pcrscr 0x%x -> 0x%x, diff %d ms,frame pts %llx,latency pts %d", pcr, apts_cal, (int)(apts_cal - pcr) / 90, pts, latency); + ALOGI("tsync -> reset pcrscr 0x%x -> 0x%x, diff %d ms,frame pts %"PRIx64",latency pts %d", pcr, apts_cal, (int)(apts_cal - pcr) / 90, pts, latency); int ret_val = sysfs_set_sysfs_str(TSYNC_APTS, buf); if (ret_val == -1) { ALOGE("unable to open file %s,err: %s", TSYNC_APTS, strerror(errno)); @@ -1763,48 +1678,48 @@ if (!(adev->out_device & AUDIO_DEVICE_OUT_ALL_SCO)) { } } } - out->last_apts_from_header = pts; + hw_sync->last_apts_from_header = pts; } #endif //ALOGI("get header body_cnt = %d, pts = %lld", out->hw_sync_body_cnt, pts); } continue; - } else if (out->hw_sync_state == HW_SYNC_STATE_BODY) { + } else if (hw_sync->hw_sync_state == HW_SYNC_STATE_BODY) { uint align; - uint m = (out->hw_sync_body_cnt < remain) ? out->hw_sync_body_cnt : remain; + uint m = (hw_sync->hw_sync_body_cnt < remain) ? hw_sync->hw_sync_body_cnt : remain; //ALOGI("m = %d", m); // process m bytes, upto end of hw_sync_body_cnt or end of remaining our_write bytes. // within m bytes, there is no hw_sync header and all are body bytes. - if (out->body_align_cnt) { + if (hw_sync->body_align_cnt) { // clear fragment first for alignment limitation on ALSA driver, which // requires each pcm_writing aligned at 16 frame boundaries // assuming data are always PCM16 based, so aligned at 64 bytes unit. - if ((m + out->body_align_cnt) < 64) { + if ((m + hw_sync->body_align_cnt) < 64) { // merge only - memcpy(&out->body_align[out->body_align_cnt], p, m); + memcpy(&hw_sync->body_align[hw_sync->body_align_cnt], p, m); p += m; remain -= m; - out->body_align_cnt += m; - out->hw_sync_body_cnt -= m; - if (out->hw_sync_body_cnt == 0) { + hw_sync->body_align_cnt += m; + hw_sync->hw_sync_body_cnt -= m; + if (hw_sync->hw_sync_body_cnt == 0) { // end of body, research for HW SYNC header - out->hw_sync_state = HW_SYNC_STATE_HEADER; - out->hw_sync_header_cnt = 0; + hw_sync->hw_sync_state = HW_SYNC_STATE_HEADER; + hw_sync->hw_sync_header_cnt = 0; continue; } //ALOGI("align cache add %d, cnt = %d", remain, out->body_align_cnt); break; } else { // merge-submit-continue - memcpy(&out->body_align[out->body_align_cnt], p, 64 - out->body_align_cnt); - p += 64 - out->body_align_cnt; - remain -= 64 - out->body_align_cnt; + memcpy(&hw_sync->body_align[hw_sync->body_align_cnt], p, 64 - hw_sync->body_align_cnt); + p += 64 - hw_sync->body_align_cnt; + remain -= 64 - hw_sync->body_align_cnt; //ALOGI("pcm_write 64, out remain %d", remain); - short *w_buf = (short*)&out->body_align[0]; + short *w_buf = (short*)&hw_sync->body_align[0]; if (need_mix) { short mix_buf[32]; @@ -1841,11 +1756,11 @@ if (!(adev->out_device & AUDIO_DEVICE_OUT_ALL_SCO)) { ret = pcm_write(out->pcm, w_buf, 64); pthread_mutex_unlock(&adev->pcm_write_lock); out->frame_write_sum += 64 / frame_size; - out->hw_sync_body_cnt -= 64 - out->body_align_cnt; - out->body_align_cnt = 0; - if (out->hw_sync_body_cnt == 0) { - out->hw_sync_state = HW_SYNC_STATE_HEADER; - out->hw_sync_header_cnt = 0; + hw_sync->hw_sync_body_cnt -= 64 - hw_sync->body_align_cnt; + hw_sync->body_align_cnt = 0; + if (hw_sync->hw_sync_body_cnt == 0) { + hw_sync->hw_sync_state = HW_SYNC_STATE_HEADER; + hw_sync->hw_sync_header_cnt = 0; } continue; } @@ -1901,25 +1816,25 @@ if (!(adev->out_device & AUDIO_DEVICE_OUT_ALL_SCO)) { remain -= m - align; //ALOGI("pcm_write %d, remain %d", m - align, remain); - out->hw_sync_body_cnt -= (m - align); - if (out->hw_sync_body_cnt == 0) { - out->hw_sync_state = HW_SYNC_STATE_HEADER; - out->hw_sync_header_cnt = 0; + hw_sync->hw_sync_body_cnt -= (m - align); + if (hw_sync->hw_sync_body_cnt == 0) { + hw_sync->hw_sync_state = HW_SYNC_STATE_HEADER; + hw_sync->hw_sync_header_cnt = 0; continue; } } if (align) { - memcpy(&out->body_align[0], p, align); + memcpy(&hw_sync->body_align[0], p, align); p += align; remain -= align; - out->body_align_cnt = align; + hw_sync->body_align_cnt = align; //ALOGI("align cache add %d, cnt = %d, remain = %d", align, out->body_align_cnt, remain); - out->hw_sync_body_cnt -= align; - if (out->hw_sync_body_cnt == 0) { - out->hw_sync_state = HW_SYNC_STATE_HEADER; - out->hw_sync_header_cnt = 0; + hw_sync->hw_sync_body_cnt -= align; + if (hw_sync->hw_sync_body_cnt == 0) { + hw_sync->hw_sync_state = HW_SYNC_STATE_HEADER; + hw_sync->hw_sync_header_cnt = 0; continue; } } @@ -1947,7 +1862,8 @@ if (!(adev->out_device & AUDIO_DEVICE_OUT_ALL_SCO)) { } exit: - latency_frames = out_get_latency(out) * out->config.rate / 1000; + clock_gettime(CLOCK_MONOTONIC, &out->timestamp); + latency_frames = out_get_latency_frames(stream); if (out->frame_write_sum >= latency_frames) { out->last_frames_postion = out->frame_write_sum - latency_frames; } else { @@ -2091,7 +2007,7 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, out->frame_write_sum += out_frames; exit: - latency_frames = out_get_latency(out) * out->config.rate / 1000; + latency_frames = out_get_latency(stream) * out->config.rate / 1000; if (out->frame_write_sum >= latency_frames) { out->last_frames_postion = out->frame_write_sum - latency_frames; } else { @@ -2131,24 +2047,24 @@ static ssize_t out_write_direct(struct audio_stream_out *stream, const void* buf char prop[PROPERTY_VALUE_MAX]; int codec_type = out->codec_type; int samesource_flag = 0; - uint32_t latency_frames; + uint32_t latency_frames = 0; uint64_t total_frame = 0; - audio_hwsync_t *p_hwsync = &adev->hwsync; + audio_hwsync_t *hw_sync = &out->hwsync; /* acquiring hw device mutex systematically is useful if a low priority thread is waiting * on the output stream mutex - e.g. executing select_mode() while holding the hw device * mutex */ - out->bytes_write_total += bytes; - ALOGV("out %p,dev %p out_write total size %lld\n", out, adev, out->bytes_write_total); + ALOGV("out_write_direct:out %p,position %zu, out_write size %"PRIu64, + out, bytes, out->frame_write_sum); pthread_mutex_lock(&adev->lock); pthread_mutex_lock(&out->lock); if (out->pause_status == true) { pthread_mutex_unlock(&adev->lock); pthread_mutex_unlock(&out->lock); - ALOGI("call out_write when pause status,size %d,(%p)\n", bytes, out); + ALOGI("call out_write when pause status,size %zu,(%p)\n", bytes, out); return 0; } - if ((out->standby) && adev->hw_sync_mode) { + if ((out->standby) && out->hw_sync_mode) { /* there are two types of raw data come to hdmi audio hal 1) compressed audio data without IEC61937 wrapped @@ -2177,20 +2093,20 @@ static ssize_t out_write_direct(struct audio_stream_out *stream, const void* buf } } void *write_buf = NULL; - int hwsync_cost_bytes = 0; - if (adev->hw_sync_mode == 1) { - int64_t cur_pts = 0xffffffff; + size_t hwsync_cost_bytes = 0; + if (out->hw_sync_mode == 1) { + uint64_t cur_pts = 0xffffffff; int outsize = 0; char tempbuf[128]; - ALOGV("before aml_audio_hwsync_find_frame bytes %d\n", bytes); + ALOGV("before aml_audio_hwsync_find_frame bytes %zu\n", bytes); hwsync_cost_bytes = aml_audio_hwsync_find_frame(out, buffer, bytes, &cur_pts, &outsize); - ALOGV("after aml_audio_hwsync_find_frame bytes remain %d,cost %d,outsize %d,pts %llx\n", + ALOGV("after aml_audio_hwsync_find_frame bytes remain %zu,cost %zu,outsize %d,pts %"PRIx64"\n", bytes - hwsync_cost_bytes, hwsync_cost_bytes, outsize, cur_pts); //TODO,skip 3 frames after flush, to tmp fix seek pts discontinue issue.need dig more // to find out why seek ppint pts frame is remained after flush.WTF. if (out->skip_frame > 0) { out->skip_frame--; - ALOGI("skip pts@%llx,cur frame size %d,cost size %d\n", cur_pts, outsize, hwsync_cost_bytes); + ALOGI("skip pts@%"PRIx64",cur frame size %d,cost size %zu\n", cur_pts, outsize, hwsync_cost_bytes); pthread_mutex_unlock(&adev->lock); pthread_mutex_unlock(&out->lock); return hwsync_cost_bytes; @@ -2199,38 +2115,38 @@ static ssize_t out_write_direct(struct audio_stream_out *stream, const void* buf // if we got the frame body,which means we get a complete frame. //we take this frame pts as the first apts. //this can fix the seek discontinue,we got a fake frame,which maybe cached before the seek - if (p_hwsync->first_apts_flag == false) { - p_hwsync->first_apts_flag = true; - p_hwsync->first_apts = cur_pts; - sprintf(tempbuf, "AUDIO_START:0x%llx", cur_pts & 0xffffffff); + if (hw_sync->first_apts_flag == false) { + hw_sync->first_apts_flag = true; + hw_sync->first_apts = cur_pts; + sprintf(tempbuf, "AUDIO_START:0x%"PRIx64"", cur_pts & 0xffffffff); ALOGI("tsync -> %s,frame size %d", tempbuf, outsize); if (sysfs_set_sysfs_str(TSYNC_EVENT, tempbuf) == -1) { ALOGE("set AUDIO_START failed \n"); } } else { - long apts; - unsigned long latency = out_get_latency(out) * 90; + uint64_t apts; + uint64_t latency = out_get_latency(stream) * 90; // check PTS discontinue, which may happen when audio track switching // discontinue means PTS calculated based on first_apts and frame_write_sum // does not match the timestamp of next audio samples if (cur_pts > latency) { - apts = (unsigned long)cur_pts - latency; + apts = cur_pts - latency; } else { apts = 0; } if (0) { //abs(cur_pts -apts) > APTS_DISCONTINUE_THRESHOLD) { - ALOGI("HW sync PTS discontinue, 0x%lx->0x%llx(from header) diff %llx,last apts %llx(from header)", - apts, cur_pts, llabs(cur_pts - apts), p_hwsync->last_apts_from_header); - p_hwsync->first_apts = cur_pts; - sprintf(tempbuf, "AUDIO_TSTAMP_DISCONTINUITY:0x%llx", cur_pts); + ALOGI("HW sync PTS discontinue, 0x%"PRIx64"->0x%"PRIx64"(from header) diff %"PRIx64",last apts %"PRIx64"(from header)", + apts, cur_pts, pts_abs(cur_pts, apts), hw_sync->last_apts_from_header); + hw_sync->first_apts = cur_pts; + sprintf(tempbuf, "AUDIO_TSTAMP_DISCONTINUITY:0x%"PRIx64"", cur_pts); if (sysfs_set_sysfs_str(TSYNC_EVENT, tempbuf) == -1) { ALOGE("unable to open file %s,err: %s", TSYNC_EVENT, strerror(errno)); } } else { - long pcr = 0; + int pcr = 0; if (get_sysfs_int16(TSYNC_PCRSCR, &pcr) == 0) { uint32_t apts_cal = apts & 0xffffffff; - if (abs(pcr - apts) < SYSTIME_CORRECTION_THRESHOLD) { + if (pts_abs(pcr, apts) < SYSTIME_CORRECTION_THRESHOLD) { // do nothing } // limit the gap handle to 0.5~5 s. @@ -2238,12 +2154,12 @@ static ssize_t out_write_direct(struct audio_stream_out *stream, const void* buf int insert_size = 0; int once_write_size = 0; if (out->codec_type == TYPE_EAC3) { - insert_size = abs(apts - pcr) / 90 * 48 * 4 * 4; + insert_size = pts_abs(apts, pcr) / 90 * 48 * 4 * 4; } else { - insert_size = abs(apts - pcr) / 90 * 48 * 4; + insert_size = pts_abs(apts, pcr) / 90 * 48 * 4; } insert_size = insert_size & (~63); - ALOGI("audio gap %d ms ,need insert data %d\n", abs(apts - pcr) / 90, insert_size); + ALOGI("audio gap %"PRIx64" ms ,need insert data %d\n", pts_abs(apts, pcr) / 90, insert_size); char *insert_buf = (char*)malloc(8192); if (insert_buf == NULL) { ALOGE("malloc size failed \n"); @@ -2268,15 +2184,15 @@ static ssize_t out_write_direct(struct audio_stream_out *stream, const void* buf else if ((pcr - apts) > APTS_DISCONTINUE_THRESHOLD_MIN && (pcr - apts) < APTS_DISCONTINUE_THRESHOLD_MAX) { //we assume one frame duration is 32 ms for DD+(6 blocks X 1536 frames,48K sample rate) if (out->codec_type == TYPE_EAC3 && outsize > 0) { - ALOGI("audio slow 0x%lx,skip frame @pts 0x%llx,pcr 0x%lx,cur apts 0x%lx\n", (pcr - apts), cur_pts, pcr, apts); + ALOGI("audio slow 0x%"PRIx64",skip frame @pts 0x%"PRIx64",pcr 0x%x,cur apts 0x%"PRIx64"\n", (pcr - apts), cur_pts, pcr, apts); out->frame_skip_sum += 1536; bytes = outsize; pthread_mutex_unlock(&adev->lock); goto exit; } } else { - sprintf(tempbuf, "0x%lx", apts); - ALOGI("tsync -> reset pcrscr 0x%lx -> 0x%lx, %s big,diff %d ms", pcr, apts, apts > pcr ? "apts" : "pcr", abs(apts - pcr) / 90); + sprintf(tempbuf, "0x%"PRIx64"", apts); + ALOGI("tsync -> reset pcrscr 0x%d -> 0x%"PRIx64", %s big,diff %"PRIx64" ms", pcr, apts, apts > (uint64_t)pcr ? "apts" : "pcr", pts_abs(apts, pcr) / 90); #if 0 int ret_val = sysfs_set_sysfs_str(TSYNC_APTS, tempbuf); if (ret_val == -1) { @@ -2290,7 +2206,7 @@ static ssize_t out_write_direct(struct audio_stream_out *stream, const void* buf } if (outsize > 0) { in_frames = outsize / frame_size; - write_buf = p_hwsync->hw_sync_body_buf; + write_buf = hw_sync->hw_sync_body_buf; } else { bytes = hwsync_cost_bytes; pthread_mutex_unlock(&adev->lock); @@ -2306,7 +2222,7 @@ static ssize_t out_write_direct(struct audio_stream_out *stream, const void* buf FILE *fp1 = fopen("/data/tmp/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); + //LOGFUNC("flen = %d---outlen=%d ", flen, out_frames * frame_size); fclose(fp1); } else { LOGFUNC("could not open file:/data/hdmi_audio_out.pcm"); @@ -2314,21 +2230,21 @@ static ssize_t out_write_direct(struct audio_stream_out *stream, const void* buf } if (codec_type_is_raw_data(out->codec_type) && !(out->flags & AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO)) { //here to do IEC61937 pack - ALOGV("IEC61937 write size %d,hw_sync_mode %d,flag %x\n", out_frames * frame_size, adev->hw_sync_mode, out->flags); + ALOGV("IEC61937 write size %zu,hw_sync_mode %d,flag %x\n", out_frames * frame_size, out->hw_sync_mode, out->flags); if (out->codec_type > 0) { // compressed audio DD/DD+ bytes = spdifenc_write((void *) buf, out_frames * frame_size); //need return actual size of this burst write - if (adev->hw_sync_mode == 1) { + if (out->hw_sync_mode == 1) { bytes = hwsync_cost_bytes; } - ALOGV("spdifenc_write return %d\n", bytes); + ALOGV("spdifenc_write return %zu\n", bytes); if (out->codec_type == TYPE_EAC3) { out->frame_write_sum = spdifenc_get_total() / 16 + out->spdif_enc_init_frame_write_sum; } else { out->frame_write_sum = spdifenc_get_total() / 4 + out->spdif_enc_init_frame_write_sum; } - ALOGV("out %p,spdifenc_get_total() / 4 %lld\n", out, spdifenc_get_total() / 16); + ALOGV("out %p,out->frame_write_sum %"PRId64"\n", out, out->frame_write_sum); } goto exit; } @@ -2412,7 +2328,7 @@ static ssize_t out_write_direct(struct audio_stream_out *stream, const void* buf pcm_stop(out->pcm); } #endif - ALOGV("write size %d\n", out_frames * frame_size); + ALOGV("write size %zu\n", out_frames * frame_size); ret = pcm_write(out->pcm, (void *) buf, out_frames * frame_size); if (ret == 0) { out->frame_write_sum += out_frames; @@ -2421,17 +2337,20 @@ static ssize_t out_write_direct(struct audio_stream_out *stream, const void* buf } exit: total_frame = out->frame_write_sum + out->frame_skip_sum; - latency_frames = out_get_latency(out) * out->config.rate / 1000; + latency_frames = out_get_latency_frames(stream); + clock_gettime(CLOCK_MONOTONIC, &out->timestamp); if (total_frame >= latency_frames) { out->last_frames_postion = total_frame - latency_frames; } else { out->last_frames_postion = total_frame; } + ALOGV("\nout %p,out->last_frames_postion %"PRId64", latency = %d\n", out, out->last_frames_postion, latency_frames); pthread_mutex_unlock(&out->lock); if (ret != 0) { usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) / out_get_sample_rate(&stream->common)); } + return bytes; } @@ -2454,7 +2373,7 @@ static int out_get_render_position(const struct audio_stream_out *stream, *dsp_frames = (uint32_t)(dsp_frame_int64 & 0xffffffff); if (out->last_dsp_frame > *dsp_frames) { ALOGI("maybe uint32_t wraparound,print something,last %u,now %u", out->last_dsp_frame, *dsp_frames); - ALOGI("wraparound,out_get_render_position return %u,playback time %llu ms,sr %d\n", *dsp_frames, + ALOGI("wraparound,out_get_render_position return %u,playback time %"PRIu64" ms,sr %d\n", *dsp_frames, out->last_frames_postion * 1000 / out->raw_61937_frame_size / out->config.rate, out->config.rate); } @@ -2483,17 +2402,18 @@ static int out_get_next_write_timestamp(const struct audio_stream_out *stream __ static int out_get_presentation_position(const struct audio_stream_out *stream, uint64_t *frames, struct timespec *timestamp) { struct aml_stream_out *out = (struct aml_stream_out *)stream; - if (frames != NULL) { - *frames = out->last_frames_postion; - } - if (timestamp != NULL) { - clock_gettime(CLOCK_MONOTONIC, timestamp); + if (!frames || !timestamp) { + return -EINVAL; } + + *frames = out->last_frames_postion; + *timestamp = out->timestamp; + if (out->flags & AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO) { - *frames = out->last_frames_postion / out->raw_61937_frame_size; + *frames /= out->raw_61937_frame_size; } - ALOGV("out_get_presentation_position %lld\n", *frames); + ALOGV("out_get_presentation_position out %p %"PRIu64", sec = %ld, nanosec = %ld\n", out, *frames, timestamp->tv_sec, timestamp->tv_nsec); return 0; } @@ -2739,7 +2659,7 @@ static void get_capture_delay(struct aml_stream_in *in, struct echo_reference_buffer *buffer) { /* read frames available in kernel driver buffer */ - size_t kernel_frames; + uint kernel_frames; struct timespec tstamp; long buf_delay; long rsmp_delay; @@ -2785,8 +2705,8 @@ static int32_t update_echo_reference(struct aml_stream_in *in, size_t frames) struct echo_reference_buffer b; 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); + ALOGV("update_echo_reference, frames = [%zu], in->ref_frames_in = [%zu], " + "b.frame_count = [%zu]", 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; @@ -2802,8 +2722,8 @@ static int32_t update_echo_reference(struct aml_stream_in *in, size_t frames) if (in->echo_reference->read(in->echo_reference, &b) == 0) { 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]", + ALOGV("update_echo_reference: in->ref_frames_in:[%zu], " + "in->ref_buf_size:[%zu], frames:[%zu], b.frame_count:[%zu]", in->ref_frames_in, in->ref_buf_size, frames, b.frame_count); } } else { @@ -2995,7 +2915,7 @@ static ssize_t process_frames(struct aml_stream_in *in, void* buffer, ssize_t fr in->proc_buf = (int16_t *)realloc(in->proc_buf, in->proc_buf_size * in->config.channels * sizeof(int16_t)); - ALOGV("process_frames(): in->proc_buf %p size extended to %d frames", + ALOGV("process_frames(): in->proc_buf %p size extended to %zu frames", in->proc_buf, in->proc_buf_size); } frames_rd = read_frames(in, @@ -3212,7 +3132,7 @@ static int adev_open_output_stream(struct audio_hw_device *dev, bool direct = false; int ret; bool hwsync_lpcm = false; - ALOGI("**enter %s(devices=0x%04x,format=%#x, ch=0x%04x, SR=%d, flags=0x%x)", __FUNCTION__, devices, + ALOGI("enter %s(devices=0x%04x,format=%#x, ch=0x%04x, SR=%d, flags=0x%x)", __FUNCTION__, devices, config->format, config->channel_mask, config->sample_rate, flags); out = (struct aml_stream_out *)calloc(1, sizeof(struct aml_stream_out)); @@ -3220,6 +3140,7 @@ static int adev_open_output_stream(struct audio_hw_device *dev, return -ENOMEM; } + out->out_device = devices; out->flags = flags; if (getprop_bool("ro.platform.has.tvuimode")) { out->is_tv_platform = 1; @@ -3244,7 +3165,11 @@ static int adev_open_output_stream(struct audio_hw_device *dev, out->stream.common.get_format = out_get_format_direct; out->stream.write = out_write_direct; out->stream.common.standby = out_standby_direct; - //out->config = pcm_config_out_direct; + if (config->format == AUDIO_FORMAT_DEFAULT) { + config->format = AUDIO_FORMAT_AC3; + } + /* set default pcm config for direct. */ + out->config = pcm_config_out_direct; out->hal_channel_mask = config->channel_mask; if (config->sample_rate == 0) { config->sample_rate = 48000; @@ -3255,9 +3180,9 @@ static int adev_open_output_stream(struct audio_hw_device *dev, digital_codec = get_codec_type(config->format); if (digital_codec == TYPE_EAC3) { out->raw_61937_frame_size = 4; - out->config.period_size = pcm_config_out.period_size * 2; + out->config.period_size = pcm_config_out_direct.period_size * 2; } else if (digital_codec == TYPE_TRUE_HD || digital_codec == TYPE_DTS_HD) { - out->config.period_size = pcm_config_out.period_size * 4 * 2; + out->config.period_size = pcm_config_out_direct.period_size * 4 * 2; out->raw_61937_frame_size = 16; } else if (digital_codec == TYPE_AC3 || digital_codec == TYPE_DTS) @@ -3273,10 +3198,13 @@ static int adev_open_output_stream(struct audio_hw_device *dev, ALOGI("for raw audio output,force alsa stereo output\n"); out->config.channels = 2; out->multich = 2; + out->hal_channel_mask = AUDIO_CHANNEL_OUT_STEREO; + //config->channel_mask = AUDIO_CHANNEL_OUT_STEREO; } - } else if (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) { - // TODO: add hwsync write here - //out->stream.write = out_write_hwsync; + } else { + // TODO: add other cases here + ALOGE("DO not support yet!!"); + return -EINVAL; } out->stream.common.get_sample_rate = out_get_sample_rate; @@ -3303,7 +3231,7 @@ static int adev_open_output_stream(struct audio_hw_device *dev, out->standby = true; out->frame_write_sum = 0; out->hw_sync_mode = false; - out->first_apts_flag = false; + out->hwsync.first_apts_flag = false; //out->hal_rate = out->config.rate; if (0/*flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC*/) { out->hw_sync_mode = true; @@ -3441,6 +3369,9 @@ static char * adev_get_parameters(const struct audio_hw_device *dev __unused, ALOGI("get hwsync id\n"); return strdup("hw_av_sync=12345678"); } + if (!strcmp(keys, AUDIO_PARAMETER_HW_AV_EAC3_SYNC)) { + return strdup("true"); + } return strdup(""); } diff --git a/audio_hw.h b/audio_hw.h index 83d3080..eb7bf8e 100644 --- a/audio_hw.h +++ b/audio_hw.h @@ -56,7 +56,7 @@ struct aml_hal_mixer { }; #define MAX_STREAM_NUM 5 - +#define HDMI_ARC_MAX_FORMAT 20 struct aml_audio_device { struct audio_hw_device hw_device; @@ -77,8 +77,7 @@ struct aml_audio_device { struct aml_stream_out *hwsync_output; struct aml_hal_mixer hal_mixer; struct pcm *pcm; - bool hw_sync_mode; - audio_hwsync_t hwsync; + unsigned hdmi_arc_ad[HDMI_ARC_MAX_FORMAT]; }; struct aml_stream_out { @@ -94,6 +93,7 @@ struct aml_stream_out { /* samplerate exposed to AudioFlinger. */ unsigned int hal_rate; audio_output_flags_t flags; + audio_devices_t out_device; struct pcm *pcm; struct resampler_itfe *resampler; char *buffer; @@ -108,15 +108,8 @@ struct aml_stream_out { uint64_t frame_write_sum; uint64_t frame_skip_sum; uint64_t last_frames_postion; - uint8_t hw_sync_header[16]; - int hw_sync_header_cnt; - int hw_sync_state; - int hw_sync_body_cnt; uint64_t spdif_enc_init_frame_write_sum; - uint64_t bytes_write_total; int skip_frame; - uint8_t body_align[64]; - uint8_t body_align_cnt; int32_t *tmp_buffer_8ch; int is_tv_platform; void *audioeffect_tmp_buffer; @@ -124,9 +117,6 @@ struct aml_stream_out { int has_EQ_lib; unsigned char pause_status; bool hw_sync_mode; - bool first_apts_flag;//flag to indicate set first apts - uint64_t first_apts; - int64_t last_apts_from_header; int has_aml_IIR_lib; float volume_l; float volume_r; @@ -135,6 +125,8 @@ struct aml_stream_out { //we need divide more when we got 61937 audio package int raw_61937_frame_size;//61937 frame size unsigned last_dsp_frame;//recorded for wraparound print info + audio_hwsync_t hwsync; + struct timespec timestamp; }; #define MAX_PREPROCESSORS 3 /* maximum one AGC + one NS + one AEC per input stream */ diff --git a/audio_hw_profile.c b/audio_hw_profile.c index 0b30d3c..548435d 100644 --- a/audio_hw_profile.c +++ b/audio_hw_profile.c @@ -1,3 +1,4 @@ +#define LOG_TAG "audio_hw_profile" #include #include #include @@ -15,8 +16,6 @@ #include "audio_hw_utils.h" -#define LOG_TAG "audio_hw_hdmi" - /* type : 0 -> playback, 1 -> capture */ @@ -158,45 +157,45 @@ char* get_hdmi_sink_cap(const char *keys) int nread = read(fd, infobuf, 1024); /* check the format cap */ if (strstr(keys, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) { - size += sprintf(aud_cap, "=%s|", "AUDIO_FORMAT_PCM_16_BIT"); + size += sprintf(aud_cap, "sup_formats=%s", "AUDIO_FORMAT_PCM_16_BIT"); if (mystrstr(infobuf, "Dobly_Digital+")) { - size += sprintf(aud_cap + size, "%s|", "AUDIO_FORMAT_E_AC3"); + size += sprintf(aud_cap + size, "|%s", "AUDIO_FORMAT_E_AC3"); } if (mystrstr(infobuf, "AC-3")) { - size += sprintf(aud_cap + size, "%s|", "AUDIO_FORMAT_AC3"); + size += sprintf(aud_cap + size, "|%s", "AUDIO_FORMAT_AC3"); } if (mystrstr(infobuf, "DTS-HD")) { - size += sprintf(aud_cap + size, "%s|", "AUDIO_FORMAT_DTS|AUDIO_FORMAT_DTSHD"); + size += sprintf(aud_cap + size, "|%s", "AUDIO_FORMAT_DTS|AUDIO_FORMAT_DTSHD"); } else if (mystrstr(infobuf, "DTS")) { - size += sprintf(aud_cap + size, "%s|", "AUDIO_FORMAT_DTS"); + size += sprintf(aud_cap + size, "|%s", "AUDIO_FORMAT_DTS"); } if (mystrstr(infobuf, "MAT")) { - size += sprintf(aud_cap + size, "%s|", "AUDIO_FORMAT_TRUEHD"); + size += sprintf(aud_cap + size, "|%s", "AUDIO_FORMAT_TRUEHD"); } } /*check the channel cap */ else if (strstr(keys, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) { /* take the 2ch suppported as default */ - size += sprintf(aud_cap, "=%s|", "AUDIO_CHANNEL_OUT_STEREO"); + size += sprintf(aud_cap, "sup_channels=%s", "AUDIO_CHANNEL_OUT_STEREO"); if (mystrstr(infobuf, "PCM, 8 ch")) { - size += sprintf(aud_cap + size, "%s|", "AUDIO_CHANNEL_OUT_5POINT1|AUDIO_CHANNEL_OUT_7POINT1"); + size += sprintf(aud_cap + size, "|%s", "AUDIO_CHANNEL_OUT_5POINT1|AUDIO_CHANNEL_OUT_7POINT1"); } else if (mystrstr(infobuf, "PCM, 6 ch")) { - size += sprintf(aud_cap + size, "%s|", "AUDIO_CHANNEL_OUT_5POINT1"); + size += sprintf(aud_cap + size, "|%s", "AUDIO_CHANNEL_OUT_5POINT1"); } } else if (strstr(keys, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) { /* take the 32/44.1/48 khz suppported as default */ - size += sprintf(aud_cap, "=%s|", "32000|44100|48000"); + size += sprintf(aud_cap, "sup_sampling_rates=%s", "32000|44100|48000"); if (mystrstr(infobuf, "88.2")) { - size += sprintf(aud_cap + size, "%s|", "88200"); + size += sprintf(aud_cap + size, "|%s", "88200"); } if (mystrstr(infobuf, "96")) { - size += sprintf(aud_cap + size, "%s|", "96000"); + size += sprintf(aud_cap + size, "|%s", "96000"); } if (mystrstr(infobuf, "176.4")) { - size += sprintf(aud_cap + size, "%s|", "176400"); + size += sprintf(aud_cap + size, "|%s", "176400"); } if (mystrstr(infobuf, "192")) { - size += sprintf(aud_cap + size, "%s|", "192000"); + size += sprintf(aud_cap + size, "|%s", "192000"); } } } diff --git a/audio_hwsync.c b/audio_hwsync.c index 12f4972..1116fab 100644 --- a/audio_hwsync.c +++ b/audio_hwsync.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -21,12 +22,12 @@ #include "audio_hwsync.h" #include "audio_hw_utils.h" #include "audio_hw.h" -//#include "hdmi_audio_hw.h" + static uint32_t aml_hwsync_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; + int 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)) { @@ -44,8 +45,7 @@ static uint32_t aml_hwsync_out_get_latency(const struct audio_stream_out *stream void aml_audio_hwsync_clear_status(struct aml_stream_out *out) { - struct aml_audio_device *adev = out->dev; - audio_hwsync_t *p_hwsync = &adev->hwsync; + audio_hwsync_t *p_hwsync = &out->hwsync; p_hwsync->first_apts_flag = 0; p_hwsync->hw_sync_state = HW_SYNC_STATE_HEADER; p_hwsync->hw_sync_header_cnt = 0; @@ -54,11 +54,10 @@ void aml_audio_hwsync_clear_status(struct aml_stream_out *out) //return bytes cost from input, int aml_audio_hwsync_find_frame(struct aml_stream_out *out, const void *in_buffer, size_t in_bytes, uint64_t *cur_pts, int *outsize) { - int remain = in_bytes; - uint8_t *p = in_buffer; - struct aml_audio_device *adev = out->dev; - audio_hwsync_t *p_hwsync = &adev->hwsync; - int time_diff = 0; + size_t remain = in_bytes; + uint8_t *p = (uint8_t *)in_buffer; + audio_hwsync_t *p_hwsync = &out->hwsync; + uint64_t time_diff = 0; //ALOGI(" --- out_write %d, cache cnt = %d, body = %d, hw_sync_state = %d", out_frames * frame_size, out->body_align_cnt, out->hw_sync_body_cnt, out->hw_sync_state); while (remain > 0) { //if (p_hwsync->hw_sync_state == HW_SYNC_STATE_RESYNC) { @@ -76,8 +75,8 @@ int aml_audio_hwsync_find_frame(struct aml_stream_out *out, const void *in_buff p_hwsync->hw_sync_header_cnt--; continue; } - if ((in_bytes-remain) > 16) - ALOGI("got the frame sync header cost %d\n",in_bytes-remain); + if ((in_bytes-remain) > 16) + ALOGI("got the frame sync header cost %zu",in_bytes-remain); p_hwsync->hw_sync_state = HW_SYNC_STATE_BODY; p_hwsync->hw_sync_body_cnt = hwsync_header_get_size(&p_hwsync->hw_sync_header[0]); p_hwsync->hw_sync_frame_size = p_hwsync->hw_sync_body_cnt; @@ -86,12 +85,12 @@ int aml_audio_hwsync_find_frame(struct aml_stream_out *out, const void *in_buff //memcpy(write_buf+write_pos,&p_hwsync->hw_sync_header[0],16); //write_pos += 16; pts = pts * 90 / 1000000; - time_diff = (abs(pts - p_hwsync->last_apts_from_header)) / 90; - ALOGV("pts %llx,frame len %d\n", pts, p_hwsync->hw_sync_body_cnt); - ALOGV("last pts %llx,diff %d ms\n", p_hwsync->last_apts_from_header, time_diff); + time_diff = pts_abs(pts, p_hwsync->last_apts_from_header) / 90; + ALOGV("pts %"PRIx64",frame len %zu\n", pts, p_hwsync->hw_sync_body_cnt); + ALOGV("last pts %"PRIx64",diff %"PRIx64" ms\n", p_hwsync->last_apts_from_header, time_diff); if (time_diff > 32) { - ALOGI("pts time gap %d ms,last %llx,cur %llx\n", time_diff, + ALOGI("pts time gap %"PRIx64" ms,last %"PRIx64",cur %"PRIx64"\n", time_diff, p_hwsync->last_apts_from_header, pts); } p_hwsync->last_apts_from_header = pts; diff --git a/audio_hwsync.h b/audio_hwsync.h index 491ab7e..99bf8ae 100644 --- a/audio_hwsync.h +++ b/audio_hwsync.h @@ -16,9 +16,9 @@ typedef struct audio_hwsync { uint8_t hw_sync_header[16]; - int hw_sync_header_cnt; + size_t hw_sync_header_cnt; int hw_sync_state; - int hw_sync_body_cnt; + size_t hw_sync_body_cnt; int hw_sync_frame_size; uint8_t hw_sync_body_buf[4096]; uint8_t body_align[64]; @@ -55,4 +55,17 @@ static inline uint32_t hwsync_header_get_size(uint8_t *header) ((uint32_t)header[7]); } +static inline uint64_t pts_abs(uint64_t a, uint64_t b) +{ + if (a >= b) + return (a - b); + else + return (b - a); +} + +struct aml_stream_out; + +void aml_audio_hwsync_clear_status(struct aml_stream_out *out); +int aml_audio_hwsync_find_frame(struct aml_stream_out *out, + const void *in_buffer, size_t in_bytes, uint64_t *cur_pts, int *outsize); #endif diff --git a/spdifenc_wrap.cpp b/spdifenc_wrap.cpp index 9eb9a8a..94878e0 100644 --- a/spdifenc_wrap.cpp +++ b/spdifenc_wrap.cpp @@ -11,22 +11,7 @@ extern "C" { #include "audio_hw_utils.h" } -#if 0 -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; -} -#endif -extern "C" int getprop_boll(const char *path); + namespace android { class MySPDIFEncoder : public SPDIFEncoder @@ -38,7 +23,8 @@ public: {}; virtual ssize_t writeOutput(const void* buffer, size_t bytes) { - ALOGV("write size %d \n", bytes); + int ret = -1; + ALOGV("write size %zu \n", bytes); #if 1 if (getprop_bool("media.spdif.outdump")) { FILE *fp1 = fopen("/data/tmp/hdmi_audio_out.spdif", "a+"); @@ -52,7 +38,11 @@ public: } #endif mTotalBytes += bytes; - return pcm_write(pcm_handle, buffer, bytes); + ret = pcm_write(pcm_handle, buffer, bytes); + if (ret) + return ret; + + return bytes; } virtual uint64_t total_bytes() { -- cgit