summaryrefslogtreecommitdiff
authorJian 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)
commitd266a655c955e3ca27d91969d7adbc44f0c192d7 (patch)
treec775d60c8bb94c2f6c47ec725f718ef993d67161
parent8c936715ae0fe847f1ac6912eafd0377ca893ac4 (diff)
downloadaudio-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
Diffstat
-rwxr-xr-x[-rw-r--r--]audio_hw.c110
-rwxr-xr-x[-rw-r--r--]audio_hwsync.h2
-rwxr-xr-x[-rw-r--r--]hdmi_audio_hw.c49
-rwxr-xr-x[-rw-r--r--]hdmi_audio_hw.h4
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;
};