summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDudemanguy <random342@airmail.cc>2023-09-26 11:21:51 -0500
committerDudemanguy <random342@airmail.cc>2023-09-27 23:10:20 +0000
commitc2c157ebeca3d072d4f48ff36228d01ebe888699 (patch)
treece275848d3021b08e6ce0bca6b9d9ee2196fb019
parent9c22d6b4382f46ed04d0daa3f8dceb96fd56f0b2 (diff)
downloadmpv-c2c157ebeca3d072d4f48ff36228d01ebe888699.tar.bz2
mpv-c2c157ebeca3d072d4f48ff36228d01ebe888699.tar.xz
demux: eagerly read subtitle streams when switching tracks while paused
a323dfae426e43451f4d3e08a9a63cb7d1c1ace9 almost fixed subtitle tracks disappearing when paused but it actually missed one part: the behavior of demux_read_packet_async_until. It's a bit unintuitive, but for subtitle streams, that function would only return the very first packet regardless of whatever pts you pass to it. So the previous commit worked on the very first subtitle, but not actually any of the others (oops). This is because subtitle streams never marked as eager and thus never actually read farther ahead. While the video is playing, this is OK, but if we're paused and switching subtitle tracks then the stream should be eagerly read. Luckily, the logic is already there in the function for this. All we have to do add an extra argument to demux_read_packet_async_until to force the stream to be read eagerly and then it just works. Be sure to unset the eager flag when we're done. Actually fixes the bug for real this time.
-rw-r--r--demux/demux.c11
-rw-r--r--demux/demux.h2
-rw-r--r--sub/dec_sub.c2
3 files changed, 10 insertions, 5 deletions
diff --git a/demux/demux.c b/demux/demux.c
index f198cfc9af..3dbca9cafb 100644
--- a/demux/demux.c
+++ b/demux/demux.c
@@ -2767,7 +2767,7 @@ static int dequeue_packet(struct demux_stream *ds, double min_pts,
// minutes away). In this situation, this function will just return -1.
int demux_read_packet_async(struct sh_stream *sh, struct demux_packet **out_pkt)
{
- return demux_read_packet_async_until(sh, MP_NOPTS_VALUE, out_pkt);
+ return demux_read_packet_async_until(sh, MP_NOPTS_VALUE, out_pkt, false);
}
// Like demux_read_packet_async(). They are the same for min_pts==MP_NOPTS_VALUE.
@@ -2775,20 +2775,25 @@ int demux_read_packet_async(struct sh_stream *sh, struct demux_packet **out_pkt)
// subtitles), then return 0 until demuxing has reached min_pts, or the queue
// overflowed, or EOF was reached, or a packet was read for this stream.
int demux_read_packet_async_until(struct sh_stream *sh, double min_pts,
- struct demux_packet **out_pkt)
+ struct demux_packet **out_pkt, bool force_eager)
{
struct demux_stream *ds = sh ? sh->ds : NULL;
*out_pkt = NULL;
if (!ds)
return -1;
+ if (force_eager)
+ ds->eager = true;
struct demux_internal *in = ds->in;
pthread_mutex_lock(&in->lock);
int r = -1;
while (1) {
r = dequeue_packet(ds, min_pts, out_pkt);
- if (in->threading || in->blocked || r != 0)
+ if (in->threading || in->blocked || r != 0) {
+ if (force_eager)
+ ds->eager = false;
break;
+ }
// Needs to actually read packets until we got a packet or EOF.
thread_work(in);
}
diff --git a/demux/demux.h b/demux/demux.h
index 08904f26cc..c84a39fed9 100644
--- a/demux/demux.h
+++ b/demux/demux.h
@@ -284,7 +284,7 @@ void demuxer_feed_caption(struct sh_stream *stream, demux_packet_t *dp);
int demux_read_packet_async(struct sh_stream *sh, struct demux_packet **out_pkt);
int demux_read_packet_async_until(struct sh_stream *sh, double min_pts,
- struct demux_packet **out_pkt);
+ struct demux_packet **out_pkt, bool force_eager);
bool demux_stream_is_selected(struct sh_stream *stream);
void demux_set_stream_wakeup_cb(struct sh_stream *sh,
void (*cb)(void *ctx), void *ctx);
diff --git a/sub/dec_sub.c b/sub/dec_sub.c
index dc26aa027e..f48eea83e2 100644
--- a/sub/dec_sub.c
+++ b/sub/dec_sub.c
@@ -294,7 +294,7 @@ bool sub_read_packets(struct dec_sub *sub, double video_pts, bool force)
double min_pts = sub->opts->sub_delay < 0 || force ? video_pts : MP_NOPTS_VALUE;
struct demux_packet *pkt;
- int st = demux_read_packet_async_until(sub->sh, min_pts, &pkt);
+ int st = demux_read_packet_async_until(sub->sh, min_pts, &pkt, force);
// Note: "wait" (st==0) happens with non-interleaved streams only, and
// then we should stop the playloop until a new enough packet has been
// seen (or the subtitle decoder's queue is full). This usually does not