Re: Issue with slave mode and playlists
Reimar Döffinger <[email protected]>
| Newsgroups | gmane.comp.video.mplayer.user |
|---|---|
| Message-ID | <[email protected]> |
On Fri, Mar 12, 2021 at 07:59:01PM -0800, Alec Bennett wrote: > I'm trying to use slave mode with a playlist, but the slave instance > doesn't advance to the next track in the playlist. > > Using version "MPlayer SVN-r38198-7 (C) 2000-2020 MPlayer Team" > > I'm running the master with the command: > mplayer -udp-master -udp-ip 127.0.0.1 -playlist ~/playlist_test.m3u > > The slave instance is: > mplayer -udp-slave -udp-ip 127.0.0.1 -playlist ~/playlist_test.m3u > > The playlist is simple: > > ~/video1.mp4 > ~/video2.mp4 > ~/video3.mp4 > > When video1.mp4 finishes, the master window starts playing video2.mp4. But > the slave window plays video1.mp4 again... > > Interestingly when I test with an old version of mplayer (version "MPlayer > 1.3.0 (Debian), built with gcc-7 (C) 2000-2016 MPlayer Team") it works... > > Is this a known issue? I am afraid that this only ever worked by pure chance... The UDP synchronization protocol can only do 2 things: - say which time position of the video to play - exit In particular, there is no "advance to next video" mechanism, so the second instance has no way of knowing it should play the next video at position 0 and not the current one. It is not in principle hard to add a send_udp command to say to advance to the next video, however it is not ideal to do so since UDP might lose messages. Also navigating e.g. backwards in the playtree would still completely break things. It's not impossible to support this use-case, but it would require a bit of thinking and work. For example it might be possible to instead send a playtree entry index together with the timestamp to ensure both instances stay in sync not only on timestamp but also file played. I attached a quick-and-dirty patch, but it would need a lot of testing, and it is very limited in what it can support. _______________________________________________ MPlayer-users mailing list [email protected] https://lists.mplayerhq.hu/mailman/listinfo/mplayer-users
0001-udp_sync-quick-and-dirty-playlist-position-sync.patch
(text/x-diff, 5.1 KB)
From ab18b3f3a4afdd51a57b4b8314e04ed880cc3490 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reimar=20D=C3=B6ffinger?= <[email protected]> Date: Tue, 16 Mar 2021 22:57:09 +0100 Subject: [PATCH] udp_sync: quick-and-dirty playlist position sync. Only works for synchronizing forward transitions in default order. --- mplayer.c | 4 +++- udp_sync.c | 24 +++++++++++++++++++----- udp_sync.h | 1 + 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/mplayer.c b/mplayer.c index ee0063e63..d3ea7acc3 100644 --- a/mplayer.c +++ b/mplayer.c @@ -2219,7 +2219,7 @@ static void handle_udp_master(double time) #ifdef CONFIG_NETWORKING if (udp_master) { char current_time[256]; - snprintf(current_time, sizeof(current_time), "%f", time); + snprintf(current_time, sizeof(current_time), "%f %i", time, udp_file_position); send_udp(udp_ip, udp_port, current_time); } #endif /* CONFIG_NETWORKING */ @@ -4087,6 +4087,8 @@ goto_enable_cache: goto_next_file: // don't jump here after ao/vo/getch initialization! + udp_file_position++; + mp_msg(MSGT_CPLAYER, MSGL_INFO, "\n"); if (benchmark) { diff --git a/udp_sync.c b/udp_sync.c index dfa77ce85..552dffd04 100644 --- a/udp_sync.c +++ b/udp_sync.c @@ -55,6 +55,7 @@ int udp_port = 23867; const char *udp_ip = "127.0.0.1"; // where the master sends datagrams // (can be a broadcast address) float udp_seek_threshold = 1.0; // how far off before we seek +int udp_file_position = 0; // quick-and-dirty, cannot handle jumping backwards so far // how far off is still considered equal #define UDP_TIMING_TOLERANCE 0.02 @@ -88,7 +89,7 @@ static void set_blocking(int fd, int blocking) // master_position if successful. if the master has exited, returns 1. // returns -1 on error or if no message received. // otherwise, returns 0. -static int get_udp(int blocking, double *master_position) +static int get_udp(int blocking, double *master_position, int *udp_file) { char mesg[100]; @@ -96,6 +97,8 @@ static int get_udp(int blocking, double *master_position) int n; static int sockfd = -1; + + *udp_file = -1; if (sockfd == -1) { #if HAVE_WINSOCK2_H DWORD tv = 30000; @@ -136,6 +139,7 @@ static int get_udp(int blocking, double *master_position) if (strcmp(mesg, "bye") == 0) return 1; *master_position = strtod(mesg, &end); + if (*end) *udp_file = strtol(end, &end, 10); if (*end) { mp_msg(MSGT_CPLAYER, MSGL_WARN, "Could not parse udp string!\n"); return -1; @@ -191,6 +195,7 @@ int udp_slave_sync(MPContext *mpctx) { // remember where the master is in the file static double udp_master_position; + static int udp_master_file; // whether we timed out before waiting for a master message static int timed_out = -1; // last time we received a valid master message @@ -205,13 +210,21 @@ int udp_slave_sync(MPContext *mpctx) } // grab any waiting datagrams without blocking - master_exited = get_udp(0, &udp_master_position); + master_exited = get_udp(0, &udp_master_position, &udp_master_file); while (!master_exited || (!timed_out && master_exited < 0)) { double my_position = mpctx->sh_video->pts; + if (udp_master_file == -1) udp_master_file = udp_file_position; + + if (udp_master_file > udp_file_position) { + mpctx->eof = PT_NEXT_ENTRY; + break; + } + // if we're way off, seek to catch up - if (FFABS(my_position - udp_master_position) > udp_seek_threshold) { + if (udp_master_file == udp_file_position && + FFABS(my_position - udp_master_position) > udp_seek_threshold) { abs_seek_pos = SEEK_ABSOLUTE; rel_seek_secs = udp_master_position; break; @@ -225,14 +238,15 @@ int udp_slave_sync(MPContext *mpctx) // without waiting. // UDP_TIMING_TOLERANCE is a small value that lets us consider // the master equal to us even if it's very slightly ahead. - if (udp_master_position + UDP_TIMING_TOLERANCE > my_position) + if (udp_master_file >= udp_file_position && + udp_master_position + UDP_TIMING_TOLERANCE > my_position) break; // the remaining case is that we're slightly ahead of the master. // usually, it just means we called get_udp() before the datagram // arrived. call get_udp again, but this time block until we receive // a datagram. - master_exited = get_udp(1, &udp_master_position); + master_exited = get_udp(1, &udp_master_position, &udp_master_file); if (master_exited < 0) timed_out = 1; } diff --git a/udp_sync.h b/udp_sync.h index d51c098d7..1143ad46a 100644 --- a/udp_sync.h +++ b/udp_sync.h @@ -31,6 +31,7 @@ extern int udp_port; extern const char *udp_ip; // where the master sends datagrams // (can be a broadcast address) extern float udp_seek_threshold; // how far off before we seek +extern int udp_file_position; void send_udp(const char *send_to_ip, int port, char *mesg); int udp_slave_sync(MPContext *mpctx); -- 2.30.2