demux: use a slightly better hack when seeking with dvd/bd

Basically just bits of a9d83eac40 that was
removed and ported to here. Not really smart but it seems like flushing
buffers during seek generally leads to better behavior and avoids some
errors. The additional stream_seek call that was being performed is
definitely bogus (will never work and spams errors). So that is skipped
for bd/dvd. SEEK_FORCE is no longer needed. Instead demux_disc calls
drop_buffers on the slave demuxer (i.e. lavf).
This commit is contained in:
Dudemanguy
2025-02-16 00:49:50 -06:00
parent 25a0c8307d
commit 4394ca5b6c
4 changed files with 35 additions and 16 deletions

View File

@@ -3819,9 +3819,6 @@ static bool queue_seek(struct demux_internal *in, double seek_pts, int flags,
bool set_backwards = flags & SEEK_SATAN;
flags &= ~(unsigned)SEEK_SATAN;
bool force_seek = flags & SEEK_FORCE;
flags &= ~(unsigned)SEEK_FORCE;
bool block = flags & SEEK_BLOCK;
flags &= ~(unsigned)SEEK_BLOCK;
@@ -3833,7 +3830,7 @@ static bool queue_seek(struct demux_internal *in, double seek_pts, int flags,
MP_VERBOSE(in, "Cached seek not possible.\n");
return false;
}
if (!in->d_thread->seekable && !force_seek) {
if (!in->d_thread->seekable) {
MP_WARN(in, "Cannot seek in this file.\n");
return false;
}

View File

@@ -95,8 +95,7 @@ struct demux_opts {
#define SEEK_CACHED (1 << 3) // allow packet cache seeks only
#define SEEK_SATAN (1 << 4) // enable backward demuxing
#define SEEK_HR (1 << 5) // hr-seek (this is a weak hint only)
#define SEEK_FORCE (1 << 6) // ignore unseekable flag
#define SEEK_BLOCK (1 << 7) // upon successfully queued seek, block readers
#define SEEK_BLOCK (1 << 6) // upon successfully queued seek, block readers
// (simplifies syncing multiple reader threads)
// Strictness of the demuxer open format check.
@@ -144,6 +143,7 @@ typedef struct demuxer_desc {
// If *pkt is NULL (the value when this function is called), the call
// will be repeated.
bool (*read_packet)(struct demuxer *demuxer, struct demux_packet **pkt);
void (*drop_buffers)(struct demuxer *demuxer);
void (*close)(struct demuxer *demuxer);
void (*seek)(struct demuxer *demuxer, double rel_seek_secs, int flags);
void (*switched_tracks)(struct demuxer *demuxer);

View File

@@ -177,16 +177,12 @@ static void d_seek(demuxer_t *demuxer, double seek_pts, int flags)
MP_VERBOSE(demuxer, "seek to: %f\n", seek_pts);
// Supposed to induce a seek reset. Does it even work? I don't know.
// It will log some bogus error messages, since the demuxer will try a
// low level seek, which will obviously not work. But it will probably
// clear its internal buffers.
demux_seek(p->slave, 0, SEEK_FACTOR | SEEK_FORCE);
stream_drop_buffers(demuxer->stream);
double seek_arg[] = {seek_pts, flags};
stream_control(demuxer->stream, STREAM_CTRL_SEEK_TO_TIME, seek_arg);
if (p->slave->desc->drop_buffers)
p->slave->desc->drop_buffers(p->slave);
p->seek_reinit = true;
}

View File

@@ -225,6 +225,7 @@ struct stream_info {
typedef struct lavf_priv {
struct stream *stream;
bool own_stream;
bool is_dvd_bd;
char *filename;
struct format_hack format_hack;
const AVInputFormat *avif;
@@ -332,9 +333,14 @@ static int64_t mp_seek(void *opaque, int64_t pos, int whence)
return -1;
int64_t current_pos = stream_tell(stream);
if (stream_seek(stream, pos) == 0) {
stream_seek(stream, current_pos);
return -1;
if (!priv->is_dvd_bd) {
if (stream_seek(stream, pos) == 0) {
stream_seek(stream, current_pos);
return -1;
}
} else {
stream_drop_buffers(stream);
stream->pos = current_pos;
}
return pos;
@@ -1171,6 +1177,15 @@ static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check)
priv->stream = NULL;
}
if (priv->stream) {
const char *sname = priv->stream->info->name;
priv->is_dvd_bd = strcmp(sname, "dvdnav") == 0 ||
strcmp(sname, "ifo_dvdnav") == 0 ||
strcmp(sname, "bd") == 0 ||
strcmp(sname, "bdnav") == 0 ||
strcmp(sname, "bdmv/bluray") == 0;
}
return 0;
fail:
@@ -1279,6 +1294,16 @@ static bool demux_lavf_read_packet(struct demuxer *demux,
return true;
}
static void demux_drop_buffers_lavf(demuxer_t *demuxer)
{
lavf_priv_t *priv = demuxer->priv;
av_seek_frame(priv->avfc, -1, 0, 1);
demux_flush(demuxer);
stream_drop_buffers(priv->stream);
avio_flush(priv->avfc->pb);
avformat_flush(priv->avfc);
}
static void demux_seek_lavf(demuxer_t *demuxer, double seek_pts, int flags)
{
lavf_priv_t *priv = demuxer->priv;
@@ -1409,6 +1434,7 @@ const demuxer_desc_t demuxer_desc_lavf = {
.desc = "libavformat",
.read_packet = demux_lavf_read_packet,
.open = demux_open_lavf,
.drop_buffers = demux_drop_buffers_lavf,
.close = demux_close_lavf,
.seek = demux_seek_lavf,
.switched_tracks = demux_lavf_switched_tracks,