author | Jian Xu <jian.xu@amlogic.com> | 2016-04-27 02:15:42 (GMT) |
---|---|---|
committer | Jian Xu <jian.xu@amlogic.com> | 2016-04-27 02:16:08 (GMT) |
commit | d266a655c955e3ca27d91969d7adbc44f0c192d7 (patch) | |
tree | c775d60c8bb94c2f6c47ec725f718ef993d67161 | |
parent | 8c936715ae0fe847f1ac6912eafd0377ca893ac4 (diff) | |
download | audio-d266a655c955e3ca27d91969d7adbc44f0c192d7.zip audio-d266a655c955e3ca27d91969d7adbc44f0c192d7.tar.gz audio-d266a655c955e3ca27d91969d7adbc44f0c192d7.tar.bz2 |
PD#124235: audio:
1) refine the frame position function
2) add skip frame function when apts smaller than pcr
Change-Id: Ibf2b6f2f5d7a83c3e28a8b95f2bd94a6ba2c31f6
-rwxr-xr-x[-rw-r--r--] | audio_hw.c | 110 | ||||
-rwxr-xr-x[-rw-r--r--] | audio_hwsync.h | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | hdmi_audio_hw.c | 49 | ||||
-rwxr-xr-x[-rw-r--r--] | hdmi_audio_hw.h | 4 |
4 files changed, 46 insertions, 119 deletions
diff --git a/audio_hw.c b/audio_hw.c index 9c7452c..75fd455 100644..100755 --- a/audio_hw.c +++ b/audio_hw.c @@ -90,7 +90,7 @@ static unsigned int DEFAULT_OUT_SAMPLING_RATE = 48000; #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/2) +#define APTS_DISCONTINUE_THRESHOLD_MIN (90000/1000*100) #define APTS_DISCONTINUE_THRESHOLD_MAX (5*90000) struct pcm_config pcm_config_out = { .channels = 2, @@ -155,8 +155,8 @@ struct aml_stream_out { struct aml_audio_device *dev; int write_threshold; bool low_power; - uint32_t frame_count; - int frame_write_sum; + uint64_t frame_write_sum; + uint64_t last_frames_postion; uint8_t hw_sync_header[16]; int hw_sync_header_cnt; int hw_sync_state; @@ -861,7 +861,7 @@ out_flush(const struct audio_stream *stream) struct aml_audio_device *adev = out->dev; pthread_mutex_lock(&out->lock); out->frame_write_sum = 0; - out->frame_count = 0; + out->last_frames_postion = 0; pthread_mutex_unlock(&out->lock); return 0; } @@ -1031,8 +1031,8 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) adev->hw_sync_mode = sync_enable; pthread_mutex_lock(&adev->lock); pthread_mutex_lock(&out->lock); - out->frame_count = 0; out->frame_write_sum = 0; + out->last_frames_postion = 0; pthread_mutex_unlock(&out->lock); pthread_mutex_unlock(&adev->lock); goto exit; @@ -1164,6 +1164,7 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, uint i, total_len; int codec_type = 0; int samesource_flag = 0; + uint32_t latency_frames = 0; if (out->pause_status == true) { out_resume(out); } @@ -1227,82 +1228,6 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, } header = (unsigned char *)buffer; -#if 0 - if (adev->first_apts_flag == false) { - uint64_t first_apts = 0; - uint32_t apts_cal; - - if ((bytes >= 16) && - hwsync_header_valid(header)) { - first_apts = hwsync_header_get_pts(header); - first_apts = first_apts * 90 / 1000000; - ALOGI("HW SYNC new first APTS %lld", first_apts); - - adev->first_apts_flag = true; - adev->first_apts = first_apts; - out->frame_write_sum = 0; - adev->last_apts_from_header = first_apts; - - sprintf(buf, "AUDIO_START:0x%lx", first_apts & 0xffffffff); - ALOGI("tsync -> %s", buf); - if (sysfs_set_sysfs_str(TSYNC_EVENT, buf) == -1) { - ALOGE("set AUDIO_START failed \n"); - } - } else { - ALOGE("HW sync header not sync, 0x%x 0x%x 0x%x 0x%x", - header[0], header[1], header[2], header[3]); - } - } else { - int64_t apts; - uint32_t latency = out_get_latency(out) * 90; - - apts = (uint64_t)out->frame_write_sum * 90000 / DEFAULT_OUT_SAMPLING_RATE; - apts += adev->first_apts; - - if ((bytes >= 16) && - hwsync_header_valid(header)) { - // 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 - uint64_t apts_from_header = hwsync_header_get_pts(header); - uint64_t apts_current = apts_from_header * 90 / 1000000; - if (abs(apts_current - adev->last_apts_from_header) > 3 * 90000) { - ALOGI("apts discontinue cur %llx,last %llx\n", apts_current, adev->last_apts_from_header); - } - ALOGI("apts from header %llx,apts %llx,write size %d\n", apts_from_header, apts, bytes); - ALOGI("last apts %llx,cur %llx \n", adev->last_apts_from_header, apts_current); - adev->last_apts_from_header = apts_current; - if (apts_from_header != apts) { - ALOGI("HW sync PTS discontinue, 0x%llx->0x%llx(from header)", - apts, apts_from_header); - } - } - - apts -= latency; - if (apts < 0) { - apts = 0; - } - - unsigned long pcr = 0; - if (get_sysfs_int16(TSYNC_PCRSCR, &pcr) == 0) { - uint32_t apts_cal = apts & 0xffffffff; - - //ALOGI("apts %x, pcr %x, diff %x\n", apts_cal, pcr, abs(pcr-apts_cal)); -#if 1 - if (abs(pcr - apts_cal) < SYSTIME_CORRECTION_THRESHOLD) { - // do nothing - } else { - sprintf(buf, "0x%lx", apts_cal); - ALOGI("tsync -> reset pcrscr 0x%x -> 0x%x, diff %d ms", pcr, apts_cal, (int)(apts_cal - pcr) / 90); - 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)); - } - } -#endif - } - } -#endif } if (out->standby) { ret = start_output_stream(out); @@ -1366,14 +1291,14 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, } } #endif - +#if 0 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) { ALOGI("to enable same source,need reset alsa,type %d,same source flag %d \n", codec_type, samesource_flag); pcm_stop(out->pcm); } - +#endif 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); @@ -1546,7 +1471,6 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, ret = pcm_write(out->pcm, &out->body_align[0], 64); out->frame_write_sum += 64 / frame_size; - out->frame_count += 64 / frame_size; out->hw_sync_body_cnt -= 64 - out->body_align_cnt; out->body_align_cnt = 0; @@ -1563,7 +1487,6 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, if ((m - align) > 0) { ret = pcm_write(out->pcm, p, m - align); out->frame_write_sum += (m - align) / frame_size; - out->frame_count += (m - align) / frame_size; p += m - align; remain -= m - align; @@ -1596,11 +1519,16 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, } else { ret = pcm_write(out->pcm, in_buffer, out_frames * frame_size); - out->frame_count += out_frames; + out->frame_write_sum += out_frames; } } exit: + latency_frames = out_get_latency(out) * out->config.rate / 1000; + if (out->frame_write_sum>= latency_frames) + out->last_frames_postion = out->frame_write_sum - latency_frames; + else + out->last_frames_postion = out->frame_write_sum; pthread_mutex_unlock(&out->lock); if (ret != 0) { usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) / @@ -1625,7 +1553,7 @@ 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; + *dsp_frames = out->last_frames_postion; return 0; } @@ -1651,12 +1579,7 @@ static int out_get_presentation_position(const struct audio_stream_out *stream, { struct aml_stream_out *out = (struct aml_stream_out *)stream; if (frames != NULL) { - uint32_t latency = out_get_latency(out) * out->config.rate / 1000; - if (out->frame_count >= latency) { - *frames = out->frame_count - latency; - } else { - *frames = out->frame_count; - } + *frames = out->last_frames_postion; } if (timestamp != NULL) { @@ -2425,7 +2348,6 @@ static int adev_open_output_stream(struct audio_hw_device *dev, out->dev = ladev; out->standby = true; output_standby = true; - out->frame_count = 0; out->frame_write_sum = 0; ladev->hw_sync_mode = false; ladev->first_apts_flag = false; diff --git a/audio_hwsync.h b/audio_hwsync.h index 0cdddab..f17144d 100644..100755 --- a/audio_hwsync.h +++ b/audio_hwsync.h @@ -12,7 +12,7 @@ #define HW_SYNC_STATE_BODY 1 #define HW_SYNC_STATE_RESYNC 2 #define APTS_DISCONTINUE_THRESHOLD (90000) -#define APTS_DISCONTINUE_THRESHOLD_MIN (90000/2) +#define APTS_DISCONTINUE_THRESHOLD_MIN (90000/1000*100) #define APTS_DISCONTINUE_THRESHOLD_MAX (5*90000) typedef struct audio_hwsync { diff --git a/hdmi_audio_hw.c b/hdmi_audio_hw.c index 378fbc7..b844836 100644..100755 --- a/hdmi_audio_hw.c +++ b/hdmi_audio_hw.c @@ -467,6 +467,7 @@ out_flush(const struct audio_stream *stream) pthread_mutex_lock(&out->lock); out->spdif_enc_init_frame_write_sum = 0; out->frame_write_sum = 0; + out->frame_skip_sum = 0; pthread_mutex_unlock(&out->lock); return 0; } @@ -581,6 +582,7 @@ out_set_parameters(struct audio_stream *stream, const char *kvpairs) pthread_mutex_lock(&out->lock); adev->hw_sync_mode = sync_enable; out->frame_write_sum = 0; + out->frame_skip_sum = 0; pthread_mutex_unlock(&adev->lock); pthread_mutex_unlock(&out->lock); goto exit; @@ -722,6 +724,8 @@ out_write(struct audio_stream_out *stream, const void *buffer, size_t bytes) char prop[PROPERTY_VALUE_MAX]; int codec_type = out->codec_type; int samesource_flag = 0; + uint32_t latency_frames; + uint64_t total_frame = 0; audio_hwsync_t *p_hwsync = &adev->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 @@ -837,9 +841,21 @@ out_write(struct audio_stream_out *stream, const void *buffer, size_t bytes) insert_size -= once_write_size; } free(insert_buf); - } else { + } + //audio pts smaller than pcr,need skip frame. + 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%x,skip frame @pts 0x%llx,pcr 0x%x,cur apts 0x%x\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%x -> 0x%x, diff %d ms", pcr, apts, abs(apts - pcr) / 90); + ALOGI("tsync -> reset pcrscr 0x%x -> 0x%x, %s big,diff %d ms", pcr, apts,apts>pcr?"apts":"pcr", abs(apts - pcr) / 90); int ret_val = sysfs_set_sysfs_str(TSYNC_APTS, tempbuf); if (ret_val == -1) { ALOGE("unable to open file %s,err: %s", TSYNC_APTS, strerror(errno)); @@ -878,7 +894,6 @@ out_write(struct audio_stream_out *stream, const void *buffer, size_t bytes) DEBUG("IEC61937 write size %d,hw_sync_mode %d,flag %x\n", out_frames * frame_size, adev->hw_sync_mode, out->flags); if (out->codec_type > 0) { // compressed audio DD/DD+ - out->write_status = 1; bytes = spdifenc_write((void *) buf, out_frames * frame_size); //need return actual size of this burst write if (adev->hw_sync_mode == 1) { @@ -890,7 +905,6 @@ out_write(struct audio_stream_out *stream, const void *buffer, size_t bytes) } else { out->frame_write_sum = spdifenc_get_total() / 4 + out->spdif_enc_init_frame_write_sum; } - out->write_status = 0; DEBUG("out %p,spdifenc_get_total() / 4 %lld\n", out, spdifenc_get_total() / 16); } goto exit; @@ -950,11 +964,17 @@ out_write(struct audio_stream_out *stream, const void *buffer, size_t bytes) DEBUG("write size %d\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; + out->frame_write_sum += out_frames; } } } exit: + total_frame = out->frame_write_sum + out->frame_skip_sum; + latency_frames = out_get_latency(out) * out->config.rate / 1000; + if (total_frame>= latency_frames) + out->last_frames_postion = total_frame - latency_frames; + else + out->last_frames_postion = total_frame; pthread_mutex_unlock(&out->lock); if (ret != 0) { usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) / @@ -995,25 +1015,11 @@ 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; - //pthread_mutex_lock (&out->lock); #if 1 if (frames != NULL) { - - if (0/*out->write_status == 1*/) { - *frames = out->last_frames_pos; - } else { - uint32_t latency_frames = out_get_latency(out) * out->config.rate / 1000; - DEBUG("out %p,adev %p latency_frames %d,out->frame_write_sum %lld\n", out, out->dev, latency_frames, out->frame_write_sum); - if (out->frame_write_sum >= latency_frames) { - *frames = out->frame_write_sum - latency_frames; - } else { - *frames = out->frame_write_sum; - } - out->last_frames_pos = *frames; - } - + *frames = out->last_frames_postion; } - DEBUG("write_status %d,%p,*frames %lld\n", out->write_status, out, *frames); + DEBUG("%p,*frames %lld\n", out, *frames); if (timestamp != NULL) { clock_gettime(CLOCK_MONOTONIC, timestamp); } @@ -1039,7 +1045,6 @@ static int out_get_presentation_position(const struct audio_stream_out *stream, } #undef TIME_TO_MS #endif - //pthread_mutex_unlock (&out->lock); return 0; } /** audio_stream_in implementation **/ diff --git a/hdmi_audio_hw.h b/hdmi_audio_hw.h index dd50423..58e0167 100644..100755 --- a/hdmi_audio_hw.h +++ b/hdmi_audio_hw.h @@ -61,10 +61,10 @@ struct aml_stream_out { int last_codec_type; int format; uint64_t frame_write_sum; + uint64_t frame_skip_sum; audio_output_flags_t flags; uint64_t spdif_enc_init_frame_write_sum; - unsigned char write_status; - uint64_t last_frames_pos; + uint64_t last_frames_postion; uint64_t bytes_write_total; unsigned char pause_status; }; |