blob: 3ccc34fde2adac4406d18ffb8b7bb44d54ac1484 [file] [log] [blame]
/*
* Copyright (c) 2020 Amlogic, Inc. All rights reserved.
*
* This source code is subject to the terms and conditions defined in the
* file 'LICENSE' which is part of this source code package.
*
* Description: test for avsync
*
* Author: song.zhao@amlogic.com
*/
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "aml_avsync.h"
#include "aml_avsync_log.h"
#define FRAME_NUM 32
#define PATTERN_32_DURATION 3750
#define PATTERN_22_DURATION 3000
#define AUDIO_FRAME_DURATION 1800 //20ms
#define AUDIO_DELAY 5400 //60ms
#define PTS_START 0x12345678
static int frame_received;
static bool audio_can_start;
static int audio_start(void *priv, avs_ascb_reason reason)
{
log_info("received");
audio_can_start = true;
return 0;
}
static void test_a(bool sync)
{
int i = 0;
void *handle = NULL, *attach_handle = NULL;
int session, session_id;
avs_start_ret ret;
int adjust = 0;
struct start_policy st_policy;
session = av_sync_open_session(&session_id);
if (session < 0) {
log_error("open fail");
exit(1);
}
handle = av_sync_create(session_id, AV_SYNC_MODE_AMASTER, AV_SYNC_TYPE_AUDIO, 0);
if (!handle) {
log_error("create fail");
goto exit;
}
if (!sync) {
/* let it timeout */
st_policy.policy = AV_SYNC_START_ALIGN;
st_policy.timeout = 2000;
ret = avs_sync_set_start_policy(handle, &st_policy);
if (ret) {
log_error("policy fail");
goto exit2;
}
}
attach_handle = av_sync_attach(session_id, AV_SYNC_TYPE_AUDIO);
if (!attach_handle) {
log_error("attach fail");
goto exit;
}
ret = av_sync_audio_start(attach_handle, PTS_START, 4500, audio_start, NULL);
if (ret == AV_SYNC_ASTART_ASYNC) {
log_info("begin wait audio start");
while (!audio_can_start)
usleep(10000);
log_info("finish wait audio start");
}
//3s, asusme each package is 10ms
for (i = 0 ; i < 300 ; i++) {
int ret;
struct audio_policy policy;
ret = av_sync_audio_render(attach_handle, adjust + PTS_START + i * 900, &policy);
if (ret) {
log_error("fail");
goto exit3;
}
switch (policy.action) {
case AV_SYNC_AA_RENDER:
log_info("render %d ms", i * 10);
usleep(10 * 1000);
break;
case AV_SYNC_AA_DROP:
log_info("drop %d ms @ %d ms", policy.delta/90, i * 10);
adjust += policy.delta;
break;
case AV_SYNC_AA_INSERT:
log_info("insert %d ms @ %d ms", -policy.delta/90, i * 10);
usleep(-policy.delta/90 * 1000 + 10 * 1000);
break;
default:
log_error("should not happen");
break;
}
}
exit3:
av_sync_destroy(attach_handle);
exit2:
av_sync_destroy(handle);
exit:
av_sync_close_session(session);
}
static void frame_free(struct vframe * frame)
{
log_info("free %d\n", (int)frame->private);
frame_received++;
}
static void test_v(int refresh_rate, int pts_interval)
{
struct vframe* frame;
int i = 0, rc;
void* handle;
int sleep_us = 1000000/refresh_rate;
struct vframe *last_frame = NULL, *pop_frame;
int session, session_id;
struct video_config config;
session = av_sync_open_session(&session_id);
if (session < 0) {
log_error("alloc fail");
exit(1);
}
handle = av_sync_create(session_id, AV_SYNC_MODE_VMASTER, AV_SYNC_TYPE_VIDEO, 2);
if (handle == 0) {
log_error("create fail");
av_sync_close_session(session);
exit(1);
}
config.delay = 2;
rc = av_sync_video_config(handle, &config);
if (rc) {
log_error("config fail");
av_sync_close_session(session_id);
exit(1);
}
frame = (struct vframe*)calloc(FRAME_NUM, sizeof(*frame));
if (!frame) {
log_error("oom");
exit(1);
}
/* push max frames */
while (i < FRAME_NUM) {
frame[i].private = (void *)i;
frame[i].pts = pts_interval * i;
frame[i].duration = pts_interval;
frame[i].free = frame_free;
if (av_sync_push_frame(handle, &frame[i])) {
log_error("queue %d fail", i);
break;
}
log_info("queue %d", i);
i++;
}
i = 0;
while (frame_received < FRAME_NUM) {
usleep(sleep_us);
pop_frame = av_sync_pop_frame(handle);
if (pop_frame)
log_info("pop frame %02d", (int)pop_frame->private);
if (pop_frame != last_frame) {
i++;
last_frame = pop_frame;
frame_received++;
}
}
frame_received = 0;
av_sync_destroy(handle);
av_sync_close_session(session);
free(frame);
}
int main(int argc, const char** argv)
{
log_set_level(LOG_TRACE);
int test_case = 0;
if (argc == 2)
test_case = atoi(argv[1]);
if (test_case == 0) {
log_info("\n----------------22 start------------\n");
test_v(60, PATTERN_22_DURATION);
log_info("\n----------------22 end--------------\n");
log_info("\n----------------32 start------------\n");
test_v(60, PATTERN_32_DURATION);
log_info("\n----------------32 start------------\n");
log_info("\n----------------41 start------------\n");
test_v(30, PATTERN_32_DURATION);
log_info("\n----------------41 end--------------\n");
log_info("\n----------------11 start------------\n");
test_v(30, PATTERN_22_DURATION);
log_info("\n----------------11 end--------------\n");
} else if (test_case == 1) {
log_info("\n----------------audio start------------\n");
test_a(true);
log_info("\n----------------audio end--------------\n");
} else if (test_case == 2) {
log_info("\n----------------audio async start------------\n");
test_a(false);
log_info("\n----------------audio end--------------\n");
}
return 0;
}