summaryrefslogtreecommitdiff
path: root/audio_hwsync.c (plain)
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
29void 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,
40int 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
128int 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