blob: 98b9efa75dbc8b951b9405e86d01dc204f7eea62
1 | /* |
2 | * Copyright (C) 2010 Amlogic Corporation. |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | |
17 | |
18 | |
19 | #define LOG_TAG "audio_hwsync" |
20 | |
21 | #include <stdint.h> |
22 | #include <inttypes.h> |
23 | #include <cutils/log.h> |
24 | #include <string.h> |
25 | |
26 | #include "audio_hw_utils.h" |
27 | #include "audio_hwsync.h" |
28 | |
29 | void aml_audio_hwsync_init(audio_hwsync_t *p_hwsync) |
30 | { |
31 | if (p_hwsync == NULL) |
32 | return; |
33 | |
34 | p_hwsync->first_apts_flag = false; |
35 | p_hwsync->hw_sync_state = HW_SYNC_STATE_HEADER; |
36 | p_hwsync->hw_sync_header_cnt = 0; |
37 | return; |
38 | } |
39 | //return bytes cost from input, |
40 | int aml_audio_hwsync_find_frame(audio_hwsync_t *p_hwsync, |
41 | const void *in_buffer, size_t in_bytes, uint64_t *cur_pts, int *outsize) |
42 | { |
43 | size_t remain = in_bytes; |
44 | uint8_t *p = (uint8_t *)in_buffer; |
45 | uint64_t time_diff = 0; |
46 | int pts_found = 0; |
47 | if (p_hwsync == NULL || in_buffer == NULL) |
48 | return 0; |
49 | |
50 | //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); |
51 | while (remain > 0) { |
52 | //if (p_hwsync->hw_sync_state == HW_SYNC_STATE_RESYNC) { |
53 | //} |
54 | if (p_hwsync->hw_sync_state == HW_SYNC_STATE_HEADER) { |
55 | //ALOGI("Add to header buffer [%d], 0x%x", p_hwsync->hw_sync_header_cnt, *p); |
56 | p_hwsync->hw_sync_header[p_hwsync->hw_sync_header_cnt++] = *p++; |
57 | remain--; |
58 | if (p_hwsync->hw_sync_header_cnt == HW_SYNC_HEADER_CNT) { |
59 | uint64_t pts; |
60 | if (!hwsync_header_valid(&p_hwsync->hw_sync_header[0])) { |
61 | //ALOGE("!!!!!!hwsync header out of sync! Resync.should not happen????"); |
62 | p_hwsync->hw_sync_state = HW_SYNC_STATE_HEADER; |
63 | memcpy(p_hwsync->hw_sync_header, p_hwsync->hw_sync_header + 1, HW_SYNC_HEADER_CNT - 1); |
64 | p_hwsync->hw_sync_header_cnt--; |
65 | continue; |
66 | } |
67 | if ((in_bytes-remain) > HW_SYNC_HEADER_CNT) |
68 | ALOGI("got the frame sync header cost %zu",in_bytes-remain); |
69 | p_hwsync->hw_sync_state = HW_SYNC_STATE_BODY; |
70 | p_hwsync->hw_sync_body_cnt = hwsync_header_get_size(&p_hwsync->hw_sync_header[0]); |
71 | p_hwsync->hw_sync_frame_size = p_hwsync->hw_sync_body_cnt; |
72 | p_hwsync->hw_sync_header_cnt = 0; |
73 | pts = hwsync_header_get_pts(&p_hwsync->hw_sync_header[0]); |
74 | pts = pts * 90 / 1000000; |
75 | time_diff = get_pts_gap(pts, p_hwsync->last_apts_from_header) / 90; |
76 | ALOGV("pts %"PRIx64",frame len %zu\n", pts, p_hwsync->hw_sync_body_cnt); |
77 | ALOGV("last pts %"PRIx64",diff %"PRIx64" ms\n", p_hwsync->last_apts_from_header, time_diff); |
78 | |
79 | if (time_diff > 32) { |
80 | ALOGI("pts time gap %"PRIx64" ms,last %"PRIx64",cur %"PRIx64"\n", time_diff, |
81 | p_hwsync->last_apts_from_header, pts); |
82 | } |
83 | p_hwsync->last_apts_from_header = pts; |
84 | *cur_pts = pts; |
85 | pts_found = 1; |
86 | //ALOGI("get header body_cnt = %d, pts = %lld", out->hw_sync_body_cnt, pts); |
87 | } |
88 | continue; |
89 | } else if (p_hwsync->hw_sync_state == HW_SYNC_STATE_BODY) { |
90 | int m = (p_hwsync->hw_sync_body_cnt < remain) ? p_hwsync->hw_sync_body_cnt : remain; |
91 | // process m bytes body with an empty fragment for alignment |
92 | if (m > 0) { |
93 | //ret = pcm_write(out->pcm, p, m - align); |
94 | #if 0 |
95 | FILE *fp1 = fopen("/data/find_body.pcm", "a+"); |
96 | if (fp1) { |
97 | int flen = fwrite((char *)p, 1, m, fp1); |
98 | //LOGFUNC("flen = %d---outlen=%d ", flen, out_frames * frame_size); |
99 | fclose(fp1); |
100 | } else { |
101 | ALOGE("could not open file:/data/find_body.pcm"); |
102 | } |
103 | #endif |
104 | memcpy(p_hwsync->hw_sync_body_buf + p_hwsync->hw_sync_frame_size - p_hwsync->hw_sync_body_cnt, p, m); |
105 | p += m; |
106 | remain -= m; |
107 | p_hwsync->hw_sync_body_cnt -= m; |
108 | if (p_hwsync->hw_sync_body_cnt == 0) { |
109 | p_hwsync->hw_sync_state = HW_SYNC_STATE_HEADER; |
110 | p_hwsync->hw_sync_header_cnt = 0; |
111 | *outsize = p_hwsync->hw_sync_frame_size; |
112 | /* |
113 | sometimes the audioflinger burst size is smaller than hwsync payload |
114 | we need use the last found pts when got a complete hwsync payload |
115 | */ |
116 | if (!pts_found) { |
117 | *cur_pts = p_hwsync->last_apts_from_header; |
118 | } |
119 | ALOGV("we found the frame total body,yeah\n"); |
120 | break;//continue; |
121 | } |
122 | } |
123 | } |
124 | } |
125 | return in_bytes - remain; |
126 | } |
127 | |
128 | int aml_audio_hwsync_set_first_pts(audio_hwsync_t *p_hwsync, uint64_t pts) |
129 | { |
130 | uint32_t pts32; |
131 | char tempbuf[128]; |
132 | |
133 | if (p_hwsync == NULL) |
134 | return -1; |
135 | |
136 | if (pts > 0xffffffff) { |
137 | ALOGE("APTS exeed the 32bit range!"); |
138 | return -1; |
139 | } |
140 | |
141 | pts32 = (uint32_t)pts; |
142 | p_hwsync->first_apts_flag = true; |
143 | p_hwsync->first_apts = pts; |
144 | sprintf(tempbuf, "AUDIO_START:0x%x", pts32); |
145 | ALOGI("hwsync set tsync -> %s", tempbuf); |
146 | if (sysfs_set_sysfs_str(TSYNC_EVENT, tempbuf) == -1) { |
147 | ALOGE("set AUDIO_START failed \n"); |
148 | return -1; |
149 | } |
150 | |
151 | return 0; |
152 | } |
153 |