blob: 1116fab6424104f44f337ce731b72fb9a30facc0
1 | #define LOG_TAG "audio_hwsync" |
2 | #include <errno.h> |
3 | #include <pthread.h> |
4 | #include <stdint.h> |
5 | #include <inttypes.h> |
6 | #include <sys/time.h> |
7 | #include <stdlib.h> |
8 | #include <sys/stat.h> |
9 | #include <fcntl.h> |
10 | #include <time.h> |
11 | #include <utils/Timers.h> |
12 | #include <cutils/log.h> |
13 | #include <cutils/str_parms.h> |
14 | #include <cutils/properties.h> |
15 | #include <linux/ioctl.h> |
16 | #include <hardware/hardware.h> |
17 | #include <system/audio.h> |
18 | #include <hardware/audio.h> |
19 | #include <sound/asound.h> |
20 | #include <tinyalsa/asoundlib.h> |
21 | |
22 | #include "audio_hwsync.h" |
23 | #include "audio_hw_utils.h" |
24 | #include "audio_hw.h" |
25 | |
26 | static uint32_t aml_hwsync_out_get_latency(const struct audio_stream_out *stream) |
27 | { |
28 | struct aml_stream_out *out = (struct aml_stream_out *)stream; |
29 | uint32_t whole_latency; |
30 | int ret; |
31 | snd_pcm_sframes_t frames = 0; |
32 | whole_latency = (out->config.period_size * out->config.period_count * 1000) / out->config.rate; |
33 | if (!out->pcm || !pcm_is_ready(out->pcm)) { |
34 | return whole_latency; |
35 | } |
36 | ret = pcm_ioctl(out->pcm, SNDRV_PCM_IOCTL_DELAY, &frames); |
37 | if (ret < 0) { |
38 | return whole_latency; |
39 | } |
40 | if (out->hal_format == AUDIO_FORMAT_E_AC3) { |
41 | frames /= 4; |
42 | } |
43 | return (uint32_t)((frames * 1000) / out->config.rate); |
44 | } |
45 | |
46 | void aml_audio_hwsync_clear_status(struct aml_stream_out *out) |
47 | { |
48 | audio_hwsync_t *p_hwsync = &out->hwsync; |
49 | p_hwsync->first_apts_flag = 0; |
50 | p_hwsync->hw_sync_state = HW_SYNC_STATE_HEADER; |
51 | p_hwsync->hw_sync_header_cnt = 0; |
52 | return; |
53 | } |
54 | //return bytes cost from input, |
55 | 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) |
56 | { |
57 | size_t remain = in_bytes; |
58 | uint8_t *p = (uint8_t *)in_buffer; |
59 | audio_hwsync_t *p_hwsync = &out->hwsync; |
60 | uint64_t time_diff = 0; |
61 | //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); |
62 | while (remain > 0) { |
63 | //if (p_hwsync->hw_sync_state == HW_SYNC_STATE_RESYNC) { |
64 | //} |
65 | if (p_hwsync->hw_sync_state == HW_SYNC_STATE_HEADER) { |
66 | //ALOGI("Add to header buffer [%d], 0x%x", out->hw_sync_header_cnt, *p); |
67 | p_hwsync->hw_sync_header[p_hwsync->hw_sync_header_cnt++] = *p++; |
68 | remain--; |
69 | if (p_hwsync->hw_sync_header_cnt == 16) { |
70 | uint64_t pts; |
71 | if (!hwsync_header_valid(&p_hwsync->hw_sync_header[0])) { |
72 | //ALOGE("!!!!!!hwsync header out of sync! Resync.should not happen????"); |
73 | p_hwsync->hw_sync_state = HW_SYNC_STATE_HEADER; |
74 | memcpy(p_hwsync->hw_sync_header, p_hwsync->hw_sync_header + 1, 15); |
75 | p_hwsync->hw_sync_header_cnt--; |
76 | continue; |
77 | } |
78 | if ((in_bytes-remain) > 16) |
79 | ALOGI("got the frame sync header cost %zu",in_bytes-remain); |
80 | p_hwsync->hw_sync_state = HW_SYNC_STATE_BODY; |
81 | p_hwsync->hw_sync_body_cnt = hwsync_header_get_size(&p_hwsync->hw_sync_header[0]); |
82 | p_hwsync->hw_sync_frame_size = p_hwsync->hw_sync_body_cnt; |
83 | p_hwsync->body_align_cnt = 0; |
84 | pts = hwsync_header_get_pts(&p_hwsync->hw_sync_header[0]); |
85 | //memcpy(write_buf+write_pos,&p_hwsync->hw_sync_header[0],16); |
86 | //write_pos += 16; |
87 | pts = pts * 90 / 1000000; |
88 | time_diff = pts_abs(pts, p_hwsync->last_apts_from_header) / 90; |
89 | ALOGV("pts %"PRIx64",frame len %zu\n", pts, p_hwsync->hw_sync_body_cnt); |
90 | ALOGV("last pts %"PRIx64",diff %"PRIx64" ms\n", p_hwsync->last_apts_from_header, time_diff); |
91 | |
92 | if (time_diff > 32) { |
93 | ALOGI("pts time gap %"PRIx64" ms,last %"PRIx64",cur %"PRIx64"\n", time_diff, |
94 | p_hwsync->last_apts_from_header, pts); |
95 | } |
96 | p_hwsync->last_apts_from_header = pts; |
97 | *cur_pts = pts; |
98 | //ALOGI("get header body_cnt = %d, pts = %lld", out->hw_sync_body_cnt, pts); |
99 | } |
100 | continue; |
101 | } else if (p_hwsync->hw_sync_state == HW_SYNC_STATE_BODY) { |
102 | int m = (p_hwsync->hw_sync_body_cnt < remain) ? p_hwsync->hw_sync_body_cnt : remain; |
103 | //ALOGI("m = %d", m); |
104 | // process m bytes body with an empty fragment for alignment |
105 | if (m > 0) { |
106 | //ret = pcm_write(out->pcm, p, m - align); |
107 | memcpy(p_hwsync->hw_sync_body_buf + p_hwsync->hw_sync_frame_size - p_hwsync->hw_sync_body_cnt, p, m); |
108 | p += m; |
109 | remain -= m; |
110 | //ALOGI("pcm_write %d, remain %d", m - align, remain); |
111 | p_hwsync->hw_sync_body_cnt -= m; |
112 | if (p_hwsync->hw_sync_body_cnt == 0) { |
113 | p_hwsync->hw_sync_state = HW_SYNC_STATE_HEADER; |
114 | p_hwsync->hw_sync_header_cnt = 0; |
115 | *outsize = p_hwsync->hw_sync_frame_size; |
116 | ALOGV("we found the frame total body,yeah\n"); |
117 | break;//continue; |
118 | } |
119 | } |
120 | } |
121 | } |
122 | return in_bytes - remain; |
123 | } |
124 |