Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't seek if dvd title >1 #696

Closed
tholin opened this issue Apr 3, 2014 · 18 comments
Closed

Can't seek if dvd title >1 #696

tholin opened this issue Apr 3, 2014 · 18 comments

Comments

@tholin
Copy link

tholin commented Apr 3, 2014

When playing back a dvd iso as "mpv --dvd-device=disc.iso dvd://1" seeking causes playback to end. Seeking works fine on the first track with dvd://0. When playing a range of titels like dvd://1-99 seeking will automatically jump to the start of the next title.

This problem existed before the dvd://1 -> dvd://0 change.
I'm using mpv-build at --master.

Playing with -v -v this is the output generated when attempting to seek:

[statusline] AV: 00:00:01 / 00:24:32 (0%) A-V:  0.000
[dvd] DVD Seek! lba=0x14B70D  cell=0  packs: 0x14B70D-0x158D8A  
[dvd] Found NAVI packet! lba=0x14B70D  len=20  
[dvd] Angle-seek synced by cell/vob IDN search!  
[dvd] Navi  new pos=0x14B722  
[dvd] Found NAVI packet! lba=0x14B722  len=291  
[dvd] DVD Seek! lba=0x14CCC8  cell=0  packs: 0x14B70D-0x158D8A  
[dvd] Found NAVI packet! lba=0x14CCC8  len=216  
[dvd] Angle-seek synced by cell/vob IDN search!  
[dvd] Navi  new pos=0x14CDA1  
[dvd] Found NAVI packet! lba=0x14CDA1  len=215  
[dvd] Navi  new pos=0x14CE79  
[dvd] Found NAVI packet! lba=0x14CE79  len=299  
[lavf] mp_seek(0x7f6ca207f050, 0, 65536)
[lavf] mp_seek(0x7f6ca207f050, 1384986623, 0)
[dvd] DVD Seek! lba=0x1F08B3  cell=3  packs: 0x1E56D3-0x1F08B4  
[dvd] dvd_next_cell: next1=0x3  
[dvd] dvd_next_cell: next2=0x3  
[dvd] Seek to/past EOF: no buffer preloaded.
[lavf] demux_lavf_fill_buffer()
[dvd] dvd_next_cell: next1=0x3  
[dvd] dvd_next_cell: next2=0x3  
[lavf] 0=mp_read(0x7f6ca207f050, 0x2d78940, 32768), pos: 4165310464, eof:1
[dvd] dvd_next_cell: next1=0x3  
[dvd] dvd_next_cell: next2=0x3  
[lavf] 0=mp_read(0x7f6ca207f050, 0x2d78940, 32768), pos: 4165310464, eof:1
[dvd] dvd_next_cell: next1=0x3  
[dvd] dvd_next_cell: next2=0x3  
[lavf] 0=mp_read(0x7f6ca207f050, 0x2d78940, 32768), pos: 4165310464, eof:1
[lavf] ds_get_packets: EOF reached (stream: video)
[lavf] demux_lavf_fill_buffer()
[dvd] dvd_next_cell: next1=0x3  
[dvd] dvd_next_cell: next2=0x3  
[lavf] 0=mp_read(0x7f6ca207f050, 0x2d78940, 32768), pos: 4165310464, eof:1
[dvd] dvd_next_cell: next1=0x3  
[dvd] dvd_next_cell: next2=0x3  
[lavf] 0=mp_read(0x7f6ca207f050, 0x2d78940, 32768), pos: 4165310464, eof:1
[dvd] dvd_next_cell: next1=0x3  
[dvd] dvd_next_cell: next2=0x3  
[lavf] 0=mp_read(0x7f6ca207f050, 0x2d78940, 32768), pos: 4165310464, eof:1
[lavf] ds_get_packets: EOF reached (stream: audio)
[statusline] AV: 00:00:01 / 00:24:32 (0%) A-V:  0.000
[cplayer] EOF code: 1
@ghost
Copy link

ghost commented Apr 3, 2014

Can't reproduce - but it could depend on the DVD.

Maybe try your luck with dvdnav://

@spacelike
Copy link

I just came here to post the exact same issue.

For my DVD there was no dvd://0 track, but dvd://1 is able to seek just fine, however anything higher and it just skips to the end.
Interestingly, the seeking works as it should for all tracks using mplayer2

attempting dvdnav:// just gives me:
No stream found to handle url dvdnav://1

@tholin
Copy link
Author

tholin commented Apr 4, 2014

I investigated this problem and think I've narrowed it down a bit.
When seeking in dvds the "stream_manages_timeline" special case in mpv/demux/demux.c::demux_seek() will be used.
It will do a call to dvd_seek_to_time() and it updates the stream parameters appropriately as far as I can tell.

The problem comes after when the DEMUXER_CTRL_RESYNC message is sent to the demux.
ffmpeg's av_seek_frame() will be called with AVSEEK_FLAG_BYTE set. This will eventually end up in seek_frame_byte()

static int seek_frame_byte(AVFormatContext *s, int stream_index,
                           int64_t pos, int flags)
{
    int64_t pos_min, pos_max;

    pos_min = s->data_offset;
    pos_max = avio_size(s->pb) - 1;

    if (pos < pos_min)
        pos = pos_min;
    else if (pos > pos_max)
        pos = pos_max;

    avio_seek(s->pb, pos, SEEK_SET);

    s->io_repositioned = 1;

    return 0;
}

The pos argument seems to be the new byte offset in the iso file after the seek. avio_size() however returns the size of the current title, not the entire iso file. When playing the first title on disc this doesn't matter because pos_min < pos < pos_max anyway but for other titles pos > pos_max. Pos will be set to pos_max and the following avio_seek will seek to the end of the title ending playback. Other seeking errors could also occur if the other title is large enough.

This problem doesn't occur in mplayer2 because the DEMUXER_CTRL_RESYNC call will just return DEMUXER_CTRL_NOTIMPL without doing anything.

I can work around the problem by not calling DEMUXER_CTRL_RESYNC at all but this will cause corruption when seeking. It seems to be the way dvdnav do it.

@ghost
Copy link

ghost commented Apr 4, 2014

Interesting! Good job.

I can work around the problem by not calling DEMUXER_CTRL_RESYNC at all but this will cause corruption when seeking. It seems to be the way dvdnav do it.

The purpose of DEMUXER_CTRL_RESYNC is to make libavformat drop its internal buffers. libavformat can have a lot of data queued, both in its internal byte-level stream buffer, and the demuxer internal packet queue. Obviously all of this must be cleared when seeking.

Normally, the demuxer seeks the stream itself. But with DVD, everything is special, and seeking by time has to be done on the stream level. So for the demuxer, the stream should look like a linear unseekable stream, which can sometimes interrupted DEMUXER_CTRL_RESYNC

@ghost ghost closed this as completed Apr 4, 2014
@ghost
Copy link

ghost commented Apr 4, 2014

Oops. Actually got on a key stroke and closed the issue. Anyway, continuing my previous post:

So for the demuxer, the stream should look like a linear unseekable stream, which can sometimes interrupted DEMUXER_CTRL_RESYNC

, which happens when seeking is done on the stream level. To make the stream seem like a linear byte stream, we also disable (or rather, not implement) stream-level seeking by byte position.

This means we should probably pretend that we don't know the byte size of the stream on the stream level. Or in other word, stream.end_pos should not be set in stream_dvd.

@ghost ghost reopened this Apr 4, 2014
@ghost
Copy link

ghost commented Apr 4, 2014

Maybe you can try this patch, though with my sample I didn't notice a change at all:

diff --git a/stream/stream_dvd.c b/stream/stream_dvd.c
index 3d6e3b3..a98e0b7 100644
--- a/stream/stream_dvd.c
+++ b/stream/stream_dvd.c
@@ -980,7 +980,6 @@ static int open_s(stream_t *stream, int mode)
     stream->control = control;
     stream->close = stream_dvd_close;
     stream->start_pos = (int64_t)d->cur_pack*2048;
-    stream->end_pos = (int64_t)(d->cur_pgc->cell_playback[d->last_cell-1].last_sector)*2048;
     MP_VERBOSE(stream, "DVD start=%d end=%d  \n",d->cur_pack,d->cur_pgc->cell_playback[d->last_cell-1].last_sector);
     stream->priv = (void*)d;
     return STREAM_OK;

@tholin
Copy link
Author

tholin commented Apr 4, 2014

Tried it but no dice.

With the patch the avio_size() call will return -1 giving pos_max = -2. Then pos > pos_max and pos will be set to -2 followed by the avio_seek to -2. Basically and any seeking will reset back to time 0.

@ghost
Copy link

ghost commented Apr 4, 2014

Basically and any seeking will reset back to time 0.

What do you mean by this?

@ghost
Copy link

ghost commented Apr 16, 2014

I've recently made some unrelated changes to dvd:// in git master. Can you test whether this affected this case?

@tholin
Copy link
Author

tholin commented Apr 16, 2014

It has changed. The main problem with playback ending when seeking is fixed but there are new problems.

  • Seeking forward works fine now but it's impossible to seek backwards. It will seek a few frames forward instead.
  • Seeking will not do a filesystem seek in the iso file, instead it reads all the data. Doing a 10 min forward seek takes 5 sek because the hard drive can't read data faster.
  • I often get corrupted frames when seeking. The corruption usually goes away at the next keyframe but sometimes it gets stuck on screen. In that case a restart of the player is the only thing that works.
  • The OSD briefly shows the wrong time when seeking. The position is shown to be the beginning of the video. Next time it redraws it shows the correct position again.
  • When --cache is enabled seeking becomes erratic. Doing a 10 sek forward seek seeks ~30 sek forward. A 10 min forward becomes a 1 sec forward seek. Seeking backwards will seek an unpredictable amount forward instead.

Some of these problems exists for dvdnav also so it might be better to file them as separate bugs?

@ghost
Copy link

ghost commented Apr 16, 2014

Sorry, I completely broke dvd:// seeking. Try this patch: http://sprunge.us/RCPG

Some of these problems exists for dvdnav also so it might be better to file them as separate bugs?

dvdnav should not be affected.

@tholin
Copy link
Author

tholin commented Apr 16, 2014

The patch fixes most problems.

There are still some video corruptions and seeking backwards is almost guaranteed to cut off sound. The sound comes back when seeking forward or when playback reach the position before the backwards seek.

Seeking backwards to a position before the start of the stream will seek forward by 1 sec instead of back. Seek back 10 min only works if playtime is >10 min.

@ghost
Copy link

ghost commented Apr 16, 2014

There are still some video corruptions and seeking backwards is almost guaranteed to cut off sound. The sound comes back when seeking forward or when playback reach the position before the backwards seek.

Even with dvdnav?

@tholin
Copy link
Author

tholin commented Apr 16, 2014

Yes, the corruptions and sound problem are the same with dvdnav.

@ghost
Copy link

ghost commented Apr 16, 2014

Did a good deal of debugging. But it seems dvdnav (as well as libdvdread) is really returning invalid data. (Or we forget to flush some data somewhere, but I didn't find anything.)

@tholin
Copy link
Author

tholin commented Jun 20, 2014

I found another DVD seek problem.

When seeking close to the end of a chapter mpv sometimes gets stuck in an infinite loop. I can only reproduce it with some dvds and only on the final chapter. I guess it happens when the seek ends up just at the end of the chapter.

gdb thread apply all bt on latest git master

Thread 13 (Thread 0x7f3572c79700 (LWP 9970)):
#0 0x00007f357d21d0ce in pthread_cond_timedwait () from /lib64/libpthread.so.0
#1 0x0000000000571805 in mpthread_cond_timedwait (cond=0x32f7c78, mutex=0x32f7c50, abstime=9223372036854775807)
at ../osdep/threads.c:25
#2 0x00000000004d4f01 in wait_wakeup (ctx=0x32f7be0, end=9223372036854775807) at ../player/client.c:241
#3 0x00000000004d5eb0 in mpv_wait_event (ctx=0x32f7be0, timeout=1e+20) at ../player/client.c:591
#4 0x00000000004ec5aa in script_wait_event (L=0x7f356c000940) at ../player/lua.c:397
#5 0x00007f3579a59c47 in luaD_precall () from /usr/lib64/liblua.so.5
#6 0x00007f3579a645f8 in luaV_execute () from /usr/lib64/liblua.so.5
#7 0x00007f3579a5a08d in luaD_call () from /usr/lib64/liblua.so.5
#8 0x00007f3579a55dc6 in lua_call () from /usr/lib64/liblua.so.5
#9 0x00000000004eb906 in run_event_loop (L=0x7f356c000940) at ../player/lua.c:141
#10 0x00000000004eb759 in wrap_cpcall (L=0x7f356c000940) at ../player/lua.c:96
#11 0x00007f3579a59c47 in luaD_precall () from /usr/lib64/liblua.so.5
#12 0x00007f3579a5a044 in luaD_call () from /usr/lib64/liblua.so.5
#13 0x00007f3579a59327 in luaD_rawrunprotected () from /usr/lib64/liblua.so.5
#14 0x00007f3579a5a242 in luaD_pcall () from /usr/lib64/liblua.so.5
#15 0x00007f3579a55e51 in lua_pcall () from /usr/lib64/liblua.so.5
#16 0x00000000004eb7cb in mp_cpcall (L=0x7f356c000940, fn=0x4eb8a3 <run_event_loop>, args=0) at ../player/lua.c:111
#17 0x00000000004ec12c in load_lua (client=0x32f7be0, fname=0x32fde00 "@osc.lua") at ../player/lua.c:294
#18 0x00000000004f5cc5 in script_thread (p=0x32f7a30) at ../player/scripting.c:82
#19 0x00007f357d218f3a in start_thread () from /lib64/libpthread.so.0
#20 0x00007f3578e049ad in clone () from /lib64/libc.so.6

Thread 12 (Thread 0x7f3568e0c700 (LWP 9972)):
#0 0x00007f357d21ccfc in pthread_cond_wait () from /lib64/libpthread.so.0
#1 0x00007f356a59d64a in radeon_drm_cs_emit_ioctl () from /usr/lib64/dri/r600_dri.so
#2 0x00007f356a59d13f in impl_thrd_routine () from /usr/lib64/dri/r600_dri.so
#3 0x00007f357d218f3a in start_thread () from /lib64/libpthread.so.0
#4 0x00007f3578e049ad in clone () from /lib64/libc.so.6

Thread 11 (Thread 0x7f355fff7700 (LWP 10193)):
#0 0x000000000050d36e in mp_dvdtimetomsec (dt=0x33014f0) at ../stream/stream_dvd_common.c:131
#1 0x000000000050b887 in dvd_seek_to_time (stream=0x37db7e0, vts_file=0x43152a0, sec=1653.5670166015625)
at ../stream/stream_dvd.c:488
#2 0x000000000050bc0d in control (stream=0x37db7e0, cmd=4, arg=0x7fff0ce504f0) at ../stream/stream_dvd.c:570
#3 0x0000000000504ffb in stream_control (s=0x37db7e0, cmd=4, arg=0x7fff0ce504f0) at ../stream/stream.c:721
#4 0x00000000004ffa99 in cache_execute_control (s=0x430af30) at ../stream/cache.c:500
#5 0x00000000004ffc3f in cache_thread (arg=0x430af30) at ../stream/cache.c:532
#6 0x00007f357d218f3a in start_thread () from /lib64/libpthread.so.0
#7 0x00007f3578e049ad in clone () from /lib64/libc.so.6

Thread 10 (Thread 0x7f35607f8700 (LWP 10194)):
#0 0x00007f357d21ccfc in pthread_cond_wait () from /lib64/libpthread.so.0
#1 0x00000000009f43ab in worker ()
#2 0x00007f357d218f3a in start_thread () from /lib64/libpthread.so.0
#3 0x00007f3578e049ad in clone () from /lib64/libc.so.6

Thread 9 (Thread 0x7f3561ffb700 (LWP 10195)):
#0 0x00007f357d21ccfc in pthread_cond_wait () from /lib64/libpthread.so.0
#1 0x00000000009f43ab in worker ()
#2 0x00007f357d218f3a in start_thread () from /lib64/libpthread.so.0
#3 0x00007f3578e049ad in clone () from /lib64/libc.so.6

Thread 8 (Thread 0x7f35627fc700 (LWP 10196)):
#0 0x00007f357d21ccfc in pthread_cond_wait () from /lib64/libpthread.so.0
#1 0x00000000009f43ab in worker ()
#2 0x00007f357d218f3a in start_thread () from /lib64/libpthread.so.0
#3 0x00007f3578e049ad in clone () from /lib64/libc.so.6

Thread 7 (Thread 0x7f356bbe7700 (LWP 10197)):
#0 0x00007f357d21ccfc in pthread_cond_wait () from /lib64/libpthread.so.0
#1 0x00000000009f43ab in worker ()
#2 0x00007f357d218f3a in start_thread () from /lib64/libpthread.so.0
#3 0x00007f3578e049ad in clone () from /lib64/libc.so.6

Thread 6 (Thread 0x7f3563fff700 (LWP 10198)):
---Type to continue, or q to quit---
#0 0x00007f357d21ccfc in pthread_cond_wait () from /lib64/libpthread.so.0
#1 0x00000000009f43ab in worker ()
#2 0x00007f357d218f3a in start_thread () from /lib64/libpthread.so.0
#3 0x00007f3578e049ad in clone () from /lib64/libc.so.6

Thread 5 (Thread 0x7f35637fe700 (LWP 10199)):
#0 0x00007f357d21ccfc in pthread_cond_wait () from /lib64/libpthread.so.0
#1 0x00000000009f43ab in worker ()
#2 0x00007f357d218f3a in start_thread () from /lib64/libpthread.so.0
#3 0x00007f3578e049ad in clone () from /lib64/libc.so.6

Thread 4 (Thread 0x7f3562ffd700 (LWP 10200)):
#0 0x00007f357d21ccfc in pthread_cond_wait () from /lib64/libpthread.so.0
#1 0x00000000009f43ab in worker ()
#2 0x00007f357d218f3a in start_thread () from /lib64/libpthread.so.0
#3 0x00007f3578e049ad in clone () from /lib64/libc.so.6

Thread 3 (Thread 0x7f35617fa700 (LWP 10201)):
#0 0x00007f357d21ccfc in pthread_cond_wait () from /lib64/libpthread.so.0
#1 0x00000000009f43ab in worker ()
#2 0x00007f357d218f3a in start_thread () from /lib64/libpthread.so.0
#3 0x00007f3578e049ad in clone () from /lib64/libc.so.6

Thread 2 (Thread 0x7f3560ff9700 (LWP 10202)):
#0 0x00007f357d21ccfc in pthread_cond_wait () from /lib64/libpthread.so.0
#1 0x0000000000497ef9 in playthread (arg=0x3c53160) at ../audio/out/push.c:318
#2 0x00007f357d218f3a in start_thread () from /lib64/libpthread.so.0
#3 0x00007f3578e049ad in clone () from /lib64/libc.so.6

Thread 1 (Thread 0x7f357d807780 (LWP 9968)):
#0 0x00007f357d21f794 in __lll_lock_wait () from /lib64/libpthread.so.0
#1 0x00007f357d2220f8 in _L_cond_lock_520 () from /lib64/libpthread.so.0
#2 0x00007f357d221ebb in __pthread_mutex_cond_lock () from /lib64/libpthread.so.0
#3 0x00007f357d21d1a6 in pthread_cond_timedwait () from /lib64/libpthread.so.0
#4 0x0000000000571805 in mpthread_cond_timedwait (cond=0x430af68, mutex=0x430af40, abstime=172400661)
at ../osdep/threads.c:25
#5 0x000000000057184f in mpthread_cond_timedwait_rel (cond=0x430af68, mutex=0x430af40, s=0.5) at ../osdep/threads.c:31
#6 0x00000000004fe870 in cache_wakeup_and_wait (s=0x430af30, retry_time=0x7fff0ce50458) at ../stream/cache.c:171
#7 0x000000000050011e in cache_control (cache=0x338d990, cmd=4, arg=0x7fff0ce504f0) at ../stream/cache.c:630
#8 0x0000000000504ffb in stream_control (s=0x338d990, cmd=4, arg=0x7fff0ce504f0) at ../stream/stream.c:721
#9 0x00000000004a462a in demux_seek (demuxer=0x36a7df0, rel_seek_secs=10, flags=0) at ../demux/demux.c:728
#10 0x00000000004f0fdc in mp_seek (mpctx=0x32c8080, seek=..., timeline_fallthrough=false) at ../player/playloop.c:280
#11 0x00000000004f149c in execute_queued_seek (mpctx=0x32c8080) at ../player/playloop.c:390
#12 0x00000000004f4712 in run_playloop (mpctx=0x32c8080) at ../player/playloop.c:1297
#13 0x00000000004e918c in play_current_file (mpctx=0x32c8080) at ../player/loadfile.c:1324
#14 0x00000000004e97d5 in mp_play_files (mpctx=0x32c8080) at ../player/loadfile.c:1456
#15 0x00000000004eab9b in mpv_main (argc=3, argv=0x7fff0ce509d8) at ../player/main.c:531
#16 0x0000000000573258 in main (argc=3, argv=0x7fff0ce509d8) at ../player/main_fn.c:13

output from perf top -p pidof mpv
31.59% mpv [.] mp_dvdtimetomsec
22.04% mpv [.] mp_msg_test
13.92% mpv [.] dvd_next_cell
10.38% mpv [.] mp_msg
8.91% mpv [.] mp_msg_va
8.16% mpv [.] dvd_read_sector
4.90% mpv [.] dvd_seek_to_time

~/.mpv/config contains
vo=opengl-hq
cache=4096
vd-lavc-show-all=no

@ghost
Copy link

ghost commented Jun 20, 2014

Tried to hack-fix it, might or might not work.

Seriously, use dvdnav://.

In fact, I'm going to rename dvdnav:// to dvd://, and you can't stop me.

@tholin
Copy link
Author

tholin commented Jun 28, 2014

The hack-fix seems to work. I can't trigger the problem anymore.

@ghost ghost added the core:dvd-bluray label Jul 18, 2015
@ghost ghost closed this as completed Jul 18, 2015
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants