blob: a43027bb56ee648e9e6b5965791ecdd8a5f3641e [file] [log] [blame]
Song Zhaoea5a0412021-01-18 16:40:08 -08001/*
2 * Copyright (c) 2021 Amlogic, Inc. All rights reserved.
3 *
4 * This source code is subject to the terms and conditions defined in the
5 * file 'LICENSE' which is part of this source code package.
6 *
7 * Description: test for pcr master mode
8 *
9 * Author: song.zhao@amlogic.com
10 */
11#include <errno.h>
12#include <sys/types.h>
13#include <sys/stat.h>
14#include <fcntl.h>
15#include <stdbool.h>
16#include <stdlib.h>
17#include <stdio.h>
18#include <string.h>
19#include <unistd.h>
20#include <pthread.h>
21
22#include "aml_avsync.h"
23#include "aml_avsync_log.h"
24
25#define FRAME_NUM 32
26#define PATTERN_32_DURATION 3750
27#define PATTERN_22_DURATION 3000
28#define REFRESH_RATE 60
29#define PTS_START 0x12345678
30
31static struct vframe *frame;
32static int frame_received;
33void *v_h, *a_h, *pcr_h;
34static pthread_t vfeed_t;
35static pthread_t afeed_t;
36static bool quit_a_thread;
37static pthread_t pcr_feed_t;
38static bool quit_pcr_thread;
39static bool audio_can_start;
40static int pts_interval = PATTERN_32_DURATION;
41
42static void frame_free(struct vframe * frame)
43{
44 log_info("free %d\n", (int)frame->private);
45 frame_received++;
46}
47
48
49static void * v_thread(void * arg)
50{
51 int i = 0;
52 int sleep_us = 1000000/REFRESH_RATE;
53 struct vframe *last_frame = NULL, *pop_frame;
54
55 /* push max frames */
56 while (i < FRAME_NUM) {
57 frame[i].private = (void *)i;
58 frame[i].pts = PTS_START + pts_interval * i;
59 frame[i].duration = pts_interval;
60 frame[i].free = frame_free;
61 if (av_sync_push_frame(v_h, &frame[i])) {
62 log_error("queue %d fail", i);
63 break;
64 }
65 log_info("queue %d", i);
66 usleep(10000);
67 i++;
68 }
69
70 i = 0;
71 while (frame_received < FRAME_NUM) {
72 usleep(sleep_us);
73 pop_frame = av_sync_pop_frame(v_h);
74 if (pop_frame)
75 log_info("pop frame %02d", (int)pop_frame->private);
76 if (pop_frame != last_frame) {
77 i++;
78 last_frame = pop_frame;
79 frame_received++;
80 log_info("frame received %d", frame_received);
81 }
82 }
83
84 return NULL;
85}
86
87static int start_v_thread()
88{
89 int ret;
90
91 frame = (struct vframe*)calloc(FRAME_NUM, sizeof(struct vframe));
92 if (!frame) {
93 log_error("oom");
94 exit(1);
95 }
96
97 ret = pthread_create(&vfeed_t, NULL, v_thread, NULL);
98 if (ret) {
99 log_error("fail");
100 exit(1);
101 }
102 return 0;
103}
104
105static void stop_v_thread()
106{
107 pthread_join(vfeed_t, NULL);
108 free(frame);
109}
110
111static int audio_start(void *priv, avs_ascb_reason reason)
112{
113 log_info("received");
114 audio_can_start = true;
115 return 0;
116}
117
118static void * a_thread(void * arg)
119{
120 int i = 0;
121 avs_start_ret ret;
122 int adjust = 0;
123
124 ret = av_sync_audio_start(a_h, PTS_START, 4500, audio_start, NULL);
125
126 if (ret == AV_SYNC_ASTART_ASYNC) {
127 log_info("begin wait audio start");
128 while (!audio_can_start)
129 usleep(10000);
130 log_info("finish wait audio start");
131 }
132
133 //5s, assume each package is 10ms
134 while (!quit_a_thread) {
135 int ret;
136 struct audio_policy policy;
137
138 ret = av_sync_audio_render(a_h, adjust + PTS_START + i * 900, &policy);
139 if (ret) {
140 log_error("fail");
141 return NULL;
142 }
143
144 switch (policy.action) {
145 case AV_SYNC_AA_RENDER:
146 log_info("render 10 ms %x", PTS_START + i * 900);
147 usleep(10 * 1000);
148 break;
149 case AV_SYNC_AA_DROP:
150 log_info("drop %d ms", policy.delta/90);
151 adjust += policy.delta;
152 break;
153 case AV_SYNC_AA_INSERT:
154 log_info("insert %d ms", (-policy.delta)/90);
155 usleep(-policy.delta/90 * 1000 + 10 * 1000);
156 break;
157 default:
158 log_error("should not happen");
159 break;
160 }
161 i++;
162 }
163 return NULL;
164}
165
166static int start_a_thread()
167{
168 int ret;
169
170 ret = pthread_create(&afeed_t, NULL, a_thread, NULL);
171 if (ret) {
172 log_error("fail");
173 exit(1);
174 }
175 return 0;
176}
177
178static void stop_a_thread()
179{
180 quit_a_thread = true;
181 pthread_join(afeed_t, NULL);
182}
183
184static void * pcr_thread(void * arg)
185{
186 int i = 0;
187 //5s, 50ms interval
188 while (!quit_pcr_thread) {
189 int ret;
190
191 ret = av_sync_set_pcr_clock(pcr_h, PTS_START + i * 4500);
192 if (ret)
193 log_error("fail");
194 log_debug("pcr is %x", PTS_START + i * 4500);
195 usleep(50000);
196 i++;
197 }
198 return NULL;
199}
200
201static int start_pcr_thread()
202{
203 int ret;
204
205 ret = pthread_create(&pcr_feed_t, NULL, pcr_thread, NULL);
206 if (ret) {
207 log_error("fail");
208 exit(1);
209 }
210 return 0;
211}
212
213static void stop_pcr_thread()
214{
215 quit_pcr_thread = true;
216 pthread_join(pcr_feed_t, NULL);
217}
218
219static void test()
220{
221 int i = 0;
222 int session, session_id;
223
224 session = av_sync_open_session(&session_id);
225 if (session < 0) {
226 log_error("fail");
227 exit(1);
228 }
229 v_h = av_sync_create(session_id, AV_SYNC_MODE_PCR_MASTER, AV_SYNC_TYPE_VIDEO, 2);
230 if (!v_h) {
231 log_error("fail");
232 exit(1);
233 }
234 a_h = av_sync_create(session_id, AV_SYNC_MODE_PCR_MASTER, AV_SYNC_TYPE_AUDIO, 0);
235 if (!a_h) {
236 log_error("fail");
237 exit(1);
238 }
239 pcr_h = av_sync_create(session_id, AV_SYNC_MODE_PCR_MASTER, AV_SYNC_TYPE_PCR, 0);
240 if (!pcr_h) {
241 log_error("fail");
242 exit(1);
243 }
244 start_v_thread();
245 start_a_thread();
246 start_pcr_thread();
247
248 //wait for 5s
249 while (i < 100) {
250 usleep(50 * 1000);
251 i++;
252 }
253
254 stop_v_thread();
255 stop_a_thread();
256 stop_pcr_thread();
257 av_sync_destroy(v_h);
258 av_sync_destroy(a_h);
259 av_sync_destroy(pcr_h);
260 av_sync_close_session(session);
261}
262
263int main(int argc, const char** argv)
264{
265 log_set_level(LOG_TRACE);
266
267 log_info("\n----------------start------------\n");
268 test();
269 log_info("\n----------------end--------------\n");
270
271 return 0;
272}