blob: 805a2cb385a088737f1cd8e541e04e4b5fd0ced7 [file] [log] [blame]
// Copyright 2016 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/* Audio Video Capturing synchronization utility
*
* This is a command-line tool running on chameleon board to monitor the
* changes of the audio page count and the video page count, and calcuate the
* time interval between the first audio/video data captured.
*/
#include <assert.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
const int controller_addr = 0xff210000;
const int controller_size = 0x10000;
char* mem;
inline int read_mem(int addr)
{
return *(int*)(mem + (addr - controller_addr));
}
inline int audio_page_count()
{
const int audio_regs_base = 0xff212000;
const int audio_reg_page_count = 0x14;
return read_mem(audio_regs_base + audio_reg_page_count);
}
inline int video_field_count()
{
const int video_regs_base = 0xff210000;
const int video_reg_frame_count = 0x20;
return read_mem(video_regs_base + video_reg_frame_count);
}
int main()
{
const int fd = open("/dev/mem", O_RDONLY | O_SYNC);
if (fd == -1) {
perror("open");
exit(1);
}
mem = mmap(NULL, controller_size, PROT_READ, MAP_SHARED, fd, controller_addr);
if (mem == MAP_FAILED) {
perror("mmap");
exit(1);
}
int last_audio_page_count = audio_page_count();
int last_video_frame_count = video_field_count();
struct timeval ta, tv;
bool done_audio = false, done_video = false;
time_t timeout = time(NULL) + 20;
while ((!done_audio || !done_video) && time(NULL) < timeout) {
if (!done_audio) {
const int current_audio_page_count = audio_page_count();
if (current_audio_page_count > last_audio_page_count) {
gettimeofday(&ta, NULL);
done_audio = true;
}
last_audio_page_count = current_audio_page_count;
}
/*
* In chameleond, VideoDumper will capture 1 frame when it selects a new
* input, so the change of the frame count from 0 to 1 may be originated
* from that frame, and the second captured frame is always the frame
* we care about.
*/
if (!done_video) {
const int current_video_frame_count = video_field_count();
if (current_video_frame_count > last_video_frame_count &&
current_video_frame_count >= 2) {
gettimeofday(&tv, NULL);
done_video = true;
}
last_video_frame_count = current_video_frame_count;
}
usleep(100);
}
if (!done_audio || !done_video) {
return -1;
}
/*
* Because tv is the time when the second frame was captured, to estimate
* the time when the first frame was captured, we need to shift it by -1/60
* second.
*/
const double diff = (tv.tv_sec - ta.tv_sec) +
(tv.tv_usec - ta.tv_usec) * 1e-6 -
1.0 / 60;
printf("%.8f\n", diff);
munmap(mem, controller_size);
close(fd);
return 0;
}