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