demux: eagerly read subtitle streams when switching tracks while paused

a323dfae42 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.
This commit is contained in:
Dudemanguy 2023-09-26 11:21:51 -05:00
parent 9c22d6b438
commit c2c157ebec
3 changed files with 10 additions and 5 deletions

View File

@ -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);
}

View File

@ -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);

View File

@ -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