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

Clean up a bit netsync.

parent 4d3a8532
...@@ -86,6 +86,13 @@ vlc_module_end() ...@@ -86,6 +86,13 @@ vlc_module_end()
/***************************************************************************** /*****************************************************************************
* Local prototypes * 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); static void Run(intf_thread_t *intf);
/***************************************************************************** /*****************************************************************************
...@@ -94,6 +101,7 @@ 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) static int Open(vlc_object_t *object)
{ {
intf_thread_t *intf = (intf_thread_t*)object; intf_thread_t *intf = (intf_thread_t*)object;
intf_sys_t *sys;
int fd; int fd;
if (!var_InheritBool(intf, "netsync-master")) { if (!var_InheritBool(intf, "netsync-master")) {
...@@ -104,17 +112,30 @@ static int Open(vlc_object_t *object) ...@@ -104,17 +112,30 @@ static int Open(vlc_object_t *object)
} }
fd = net_ConnectUDP(VLC_OBJECT(intf), psz_master, NETSYNC_PORT, -1); fd = net_ConnectUDP(VLC_OBJECT(intf), psz_master, NETSYNC_PORT, -1);
free(psz_master); free(psz_master);
} } else {
else
fd = net_ListenUDP1(VLC_OBJECT(intf), NULL, NETSYNC_PORT); fd = net_ListenUDP1(VLC_OBJECT(intf), NULL, NETSYNC_PORT);
}
if (fd == -1) { if (fd == -1) {
msg_Err(intf, "Netsync socket failure"); msg_Err(intf, "Netsync socket failure");
return VLC_EGENERIC; 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; 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; return VLC_SUCCESS;
} }
...@@ -124,40 +145,127 @@ static int Open(vlc_object_t *object) ...@@ -124,40 +145,127 @@ static int Open(vlc_object_t *object)
void Close(vlc_object_t *object) void Close(vlc_object_t *object)
{ {
intf_thread_t *intf = (intf_thread_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 * Run: interface thread
*****************************************************************************/ *****************************************************************************/
static void Run(intf_thread_t *intf) static void Run(intf_thread_t *intf)
{ {
#define MAX_MSG_LENGTH (2 * sizeof(int64_t)) intf_sys_t *sys = intf->p_sys;
int canc = vlc_savecancel();
input_thread_t *input = NULL;
char data[MAX_MSG_LENGTH];
int fd = (intptr_t)intf->p_sys;
playlist_t *playlist = pl_Hold(intf); int canc = vlc_savecancel();
int timeout = var_InheritInteger(intf, "netsync-timeout");
if (timeout < 500)
timeout = 500;
bool is_master = var_InheritBool(intf, "netsync-master");
/* High priority thread */ /* High priority thread */
vlc_thread_set_priority(intf, VLC_THREAD_PRIORITY_INPUT); vlc_thread_set_priority(intf, VLC_THREAD_PRIORITY_INPUT);
while (vlc_object_alive(intf)) { while (vlc_object_alive(intf)) {
/* Update the input */ /* Update the input */
if (input == NULL) { if (sys->input == NULL) {
input = playlist_CurrentInput(playlist); sys->input = playlist_CurrentInput(sys->playlist);
} else if (input->b_dead || !vlc_object_alive(input)) { } else if (sys->input->b_dead || !vlc_object_alive(sys->input)) {
vlc_object_release(input); vlc_object_release(sys->input);
input = NULL; sys->input = NULL;
} }
if (input == NULL) { if (sys->input == NULL) {
/* Wait a bit */ /* Wait a bit */
msleep(INTF_IDLE_SLEEP); msleep(INTF_IDLE_SLEEP);
continue; continue;
...@@ -166,124 +274,14 @@ static void Run(intf_thread_t *intf) ...@@ -166,124 +274,14 @@ static void Run(intf_thread_t *intf)
/* /*
* We now have an input * We now have an input
*/ */
if (sys->is_master)
/* Initialize file descriptor set and timeout (0.5s) */ Master(intf);
/* 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
}
else else
{ Slave(intf);
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);
}
} }
if (input) if (sys->input)
vlc_object_release(input); vlc_object_release(sys->input);
pl_Release(intf);
vlc_restorecancel(canc); 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