blob: a04fc70dfcc9caddedde919fe2fefc5e1fb7e9a2
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 | |
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", out->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 == 16) { |
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, 15); |
64 | p_hwsync->hw_sync_header_cnt--; |
65 | continue; |
66 | } |
67 | if ((in_bytes-remain) > 16) |
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->body_align_cnt = 0; |
73 | pts = hwsync_header_get_pts(&p_hwsync->hw_sync_header[0]); |
74 | //memcpy(write_buf+write_pos,&p_hwsync->hw_sync_header[0],16); |
75 | //write_pos += 16; |
76 | pts = pts * 90 / 1000000; |
77 | time_diff = get_pts_gap(pts, p_hwsync->last_apts_from_header) / 90; |
78 | ALOGV("pts %"PRIx64",frame len %zu\n", pts, p_hwsync->hw_sync_body_cnt); |
79 | ALOGV("last pts %"PRIx64",diff %"PRIx64" ms\n", p_hwsync->last_apts_from_header, time_diff); |
80 | |
81 | if (time_diff > 32) { |
82 | ALOGI("pts time gap %"PRIx64" ms,last %"PRIx64",cur %"PRIx64"\n", time_diff, |
83 | p_hwsync->last_apts_from_header, pts); |
84 | } |
85 | p_hwsync->last_apts_from_header = pts; |
86 | *cur_pts = pts; |
87 | //ALOGI("get header body_cnt = %d, pts = %lld", out->hw_sync_body_cnt, pts); |
88 | } |
89 | continue; |
90 | } else if (p_hwsync->hw_sync_state == HW_SYNC_STATE_BODY) { |
91 | int m = (p_hwsync->hw_sync_body_cnt < remain) ? p_hwsync->hw_sync_body_cnt : remain; |
92 | //ALOGI("m = %d", m); |
93 | // process m bytes body with an empty fragment for alignment |
94 | if (m > 0) { |
95 | //ret = pcm_write(out->pcm, p, m - align); |
96 | memcpy(p_hwsync->hw_sync_body_buf + p_hwsync->hw_sync_frame_size - p_hwsync->hw_sync_body_cnt, p, m); |
97 | p += m; |
98 | remain -= m; |
99 | //ALOGI("pcm_write %d, remain %d", m - align, remain); |
100 | p_hwsync->hw_sync_body_cnt -= m; |
101 | if (p_hwsync->hw_sync_body_cnt == 0) { |
102 | p_hwsync->hw_sync_state = HW_SYNC_STATE_HEADER; |
103 | p_hwsync->hw_sync_header_cnt = 0; |
104 | *outsize = p_hwsync->hw_sync_frame_size; |
105 | ALOGV("we found the frame total body,yeah\n"); |
106 | break;//continue; |
107 | } |
108 | } |
109 | } |
110 | } |
111 | return in_bytes - remain; |
112 | } |
113 | |
114 | int aml_audio_hwsync_set_first_pts(audio_hwsync_t *p_hwsync, uint64_t pts) |
115 | { |
116 | uint32_t pts32; |
117 | char tempbuf[128]; |
118 | |
119 | if (p_hwsync == NULL) |
120 | return -1; |
121 | |
122 | if (pts > 0xffffffff) { |
123 | ALOGE("APTS exeed the 32bit range!"); |
124 | return -1; |
125 | } |
126 | |
127 | pts32 = (uint32_t)pts; |
128 | p_hwsync->first_apts_flag = true; |
129 | p_hwsync->first_apts = pts; |
130 | sprintf(tempbuf, "AUDIO_START:0x%x", pts32); |
131 | ALOGI("hwsync set tsync -> %s", tempbuf); |
132 | if (sysfs_set_sysfs_str(TSYNC_EVENT, tempbuf) == -1) { |
133 | ALOGE("set AUDIO_START failed \n"); |
134 | return -1; |
135 | } |
136 | |
137 | return 0; |
138 | } |
139 |