summaryrefslogtreecommitdiff
path: root/audio_hwsync.c (plain)
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
26static 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
46void 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,
55int 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