Commit 188b465f authored by Laurent Aimar's avatar Laurent Aimar

Clean up a bit netsync.

parent 4d3a8532
......@@ -86,6 +86,13 @@ vlc_module_end()
/*****************************************************************************
* Local prototypes
*****************************************************************************/
struct intf_sys_t {
int fd;
int timeout;
bool is_master;
playlist_t *playlist;
input_thread_t *input;
};
static void Run(intf_thread_t *intf);
/*****************************************************************************
......@@ -94,6 +101,7 @@ static void Run(intf_thread_t *intf);
static int Open(vlc_object_t *object)
{
intf_thread_t *intf = (intf_thread_t*)object;
intf_sys_t *sys;
int fd;
if (!var_InheritBool(intf, "netsync-master")) {
......@@ -104,17 +112,30 @@ static int Open(vlc_object_t *object)
}
fd = net_ConnectUDP(VLC_OBJECT(intf), psz_master, NETSYNC_PORT, -1);
free(psz_master);
}
else
} else {
fd = net_ListenUDP1(VLC_OBJECT(intf), NULL, NETSYNC_PORT);
}
if (fd == -1) {
msg_Err(intf, "Netsync socket failure");
return VLC_EGENERIC;
}
intf->p_sys = (void *)(intptr_t)fd;
intf->p_sys = sys = malloc(sizeof(*sys));
if (!sys) {
net_Close(fd);
return VLC_ENOMEM;
}
intf->pf_run = Run;
sys->fd = fd;
sys->is_master = var_InheritBool(intf, "netsync-master");
sys->timeout = var_InheritInteger(intf, "netsync-timeout");
if (sys->timeout < 500)
sys->timeout = 500;
sys->playlist = pl_Hold(intf);
sys->input = NULL;
return VLC_SUCCESS;
}
......@@ -124,40 +145,127 @@ static int Open(vlc_object_t *object)
void Close(vlc_object_t *object)
{
intf_thread_t *intf = (intf_thread_t*)object;
intf_sys_t *sys = intf->p_sys;
net_Close((intptr_t)intf->p_sys);
pl_Release(intf);
net_Close(sys->fd);
free(sys);
}
static void Master(intf_thread_t *intf)
{
intf_sys_t *sys = intf->p_sys;
struct pollfd ufd = { .fd = sys->fd, .events = POLLIN, };
uint64_t data[2];
/* Don't block */
if (poll(&ufd, 1, sys->timeout) <= 0)
return;
/* We received something */
struct sockaddr_storage from;
unsigned struct_size = sizeof(from);
recvfrom(sys->fd, data, sizeof(data), 0,
(struct sockaddr*)&from, &struct_size);
mtime_t master_system;
if (input_GetPcrSystem(sys->input, &master_system))
return;
data[0] = hton64(mdate());
data[1] = hton64(master_system);
/* Reply to the sender */
sendto(sys->fd, data, sizeof(data), 0,
(struct sockaddr *)&from, struct_size);
#if 0
/* not sure we need the client information to sync,
since we are the master anyway */
mtime_t client_system = ntoh64(data[0]);
msg_Dbg(intf, "Master clockref: %"PRId64" -> %"PRId64", from %s "
"(date: %"PRId64")", client_system, master_system,
(from.ss_family == AF_INET) ? inet_ntoa(((struct sockaddr_in *)&from)->sin_addr)
: "non-IPv4", date);
#endif
}
static void Slave(intf_thread_t *intf)
{
intf_sys_t *sys = intf->p_sys;
struct pollfd ufd = { .fd = sys->fd, .events = POLLIN, };
uint64_t data[2];
mtime_t system;
if (input_GetPcrSystem(sys->input, &system))
goto wait;
/* Send clock request to the master */
data[0] = hton64(system);
const mtime_t send_date = mdate();
if (send(sys->fd, data, sizeof(data[0]), 0) <= 0)
goto wait;
/* Don't block */
int ret = poll(&ufd, 1, sys->timeout);
if (ret == 0)
return;
if (ret < 0)
goto wait;
const mtime_t receive_date = mdate();
if (recv(sys->fd, data, sizeof(data), 0) <= 0)
goto wait;
const mtime_t master_date = ntoh64(data[0]);
const mtime_t master_system = ntoh64(data[1]);
const mtime_t diff_date = receive_date -
((receive_date - send_date) / 2 + master_date);
if (master_system > 0) {
mtime_t client_system;
if (input_GetPcrSystem(sys->input, &client_system))
goto wait;
const mtime_t diff_system = client_system - master_system - diff_date;
if (diff_system != 0) {
input_ModifyPcrSystem(sys->input, true, master_system - diff_date);
#if 0
msg_Dbg(intf, "Slave clockref: %"PRId64" -> %"PRId64" -> %"PRId64","
" clock diff: %"PRId64", diff: %"PRId64"",
system, master_system, client_system,
diff_system, diff_date);
#endif
}
}
wait:
msleep(INTF_IDLE_SLEEP);
}
/*****************************************************************************
* Run: interface thread
*****************************************************************************/
static void Run(intf_thread_t *intf)
{
#define MAX_MSG_LENGTH (2 * sizeof(int64_t))
int canc = vlc_savecancel();
input_thread_t *input = NULL;
char data[MAX_MSG_LENGTH];
int fd = (intptr_t)intf->p_sys;
intf_sys_t *sys = intf->p_sys;
playlist_t *playlist = pl_Hold(intf);
int timeout = var_InheritInteger(intf, "netsync-timeout");
if (timeout < 500)
timeout = 500;
bool is_master = var_InheritBool(intf, "netsync-master");
int canc = vlc_savecancel();
/* High priority thread */
vlc_thread_set_priority(intf, VLC_THREAD_PRIORITY_INPUT);
while (vlc_object_alive(intf)) {
/* Update the input */
if (input == NULL) {
input = playlist_CurrentInput(playlist);
} else if (input->b_dead || !vlc_object_alive(input)) {
vlc_object_release(input);
input = NULL;
if (sys->input == NULL) {
sys->input = playlist_CurrentInput(sys->playlist);
} else if (sys->input->b_dead || !vlc_object_alive(sys->input)) {
vlc_object_release(sys->input);
sys->input = NULL;
}
if (input == NULL) {
if (sys->input == NULL) {
/* Wait a bit */
msleep(INTF_IDLE_SLEEP);
continue;
......@@ -166,124 +274,14 @@ static void Run(intf_thread_t *intf)
/*
* We now have an input
*/
/* Initialize file descriptor set and timeout (0.5s) */
/* FIXME: arbitrary tick */
struct pollfd ufd = { .fd = fd, .events = POLLIN, };
if (is_master) {
struct sockaddr_storage from;
mtime_t master_system;
mtime_t client_system;
mtime_t date;
int struct_size, read_size, ret;
/* Don't block */
ret = poll(&ufd, 1, timeout);
if (ret <= 0)
continue;
/* We received something */
struct_size = sizeof(from);
read_size = recvfrom(fd, data, MAX_MSG_LENGTH, 0,
(struct sockaddr*)&from,
(unsigned int *)&struct_size);
/* not sure we need the client information to sync,
since we are the master anyway */
client_system = ntoh64(*(int64_t *)data);
date = mdate();
if (input_GetPcrSystem(input, &master_system))
continue;
*((int64_t *)data) = hton64(date);
*(((int64_t *)data)+1) = hton64(master_system);
/* Reply to the sender */
sendto(fd, data, 2 * sizeof(int64_t), 0,
(struct sockaddr *)&from, struct_size);
#if 0
msg_Dbg(intf, "Master clockref: %"PRId64" -> %"PRId64", from %s "
"(date: %"PRId64")", client_system, master_system,
(from.ss_family == AF_INET) ? inet_ntoa(((struct sockaddr_in *)&from)->sin_addr)
: "non-IPv4", date);
#endif
}
if (sys->is_master)
Master(intf);
else
{
mtime_t master_system;
mtime_t client_system;
mtime_t system = 0;
mtime_t send_date, receive_date;
mtime_t diff_date, master_date;
int sent, read_size, ret;
if (input_GetPcrSystem(input, &system)) {
msleep(INTF_IDLE_SLEEP);
continue;
}
/* Send clock request to the master */
send_date = mdate();
*((int64_t *)data) = hton64(system);
sent = send(fd, data, sizeof(int64_t), 0);
if (sent <= 0) {
msleep(INTF_IDLE_SLEEP);
continue;
}
/* Don't block */
ret = poll(&ufd, 1, timeout);
if (ret == 0)
continue;
if (ret < 0) {
msleep(INTF_IDLE_SLEEP);
continue;
}
receive_date = mdate();
read_size = recv(fd, data, MAX_MSG_LENGTH, 0);
if (read_size <= 0) {
msleep(INTF_IDLE_SLEEP);
continue;
}
master_date = ntoh64(*(int64_t *)data);
master_system = ntoh64(*(((int64_t *)data)+1)); /* system date */
diff_date = receive_date -
((receive_date - send_date) / 2 + master_date);
if (input && master_system > 0) {
mtime_t diff_system;
if (input_GetPcrSystem(input, &client_system)) {
msleep(INTF_IDLE_SLEEP);
continue;
}
diff_system = client_system - master_system - diff_date;
if (diff_system != 0) {
input_ModifyPcrSystem(input, true, master_system - diff_date);
#if 0
msg_Dbg(intf, "Slave clockref: %"PRId64" -> %"PRId64" -> %"PRId64","
" clock diff: %"PRId64", diff: %"PRId64"",
system, master_system, client_system,
diff_system, diff_date);
#endif
}
}
msleep(INTF_IDLE_SLEEP);
}
Slave(intf);
}
if (input)
vlc_object_release(input);
pl_Release(intf);
if (sys->input)
vlc_object_release(sys->input);
vlc_restorecancel(canc);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment