Hi all. First, some background about me. I am very new to open-source project contribution. So, my apologies in advance for any inexperienced gaffes in my tone or approach. Also, I sent an earlier version, but apparently it was too large and needed moderator approval. Please ignore if you get it again.
While working with VLC I noticed that libdvdnav does not accurately handle setting position by time. Specifically, there are two methods that seem to address this functionality, but both have issues: 1. dvdnav_time_play in navigation.c This is not implemented, so it is not usable. printerr("Not implemented yet."); 2. dvdnav_time_search in searching.c: This function uses interpolation over a cell to get to a time, which is inaccurate. The comment indicates as much /* FIXME: right now, this function does not use the time tables but interpolates only the cell times */ With that in mind, I decided to try to implement an accurate method. As it turns out, this is not a trivial issue. I came up with an approach that does seem to work, but with a few reservations: - the approach is a bit complicated It uses VTS_TMAPTI and VTS_VOBU_ADMAP to get to time. I detail more below. - the approach may fail on poorly-authored dvds If a DVD has a corrupt VTS_VOBU_ADMAP it will not work I detail more in this thread: http://forum.videolan.org/viewtopic.php?f=32&t=76308&start=15. I am reposting my last post below. It is verbose, but hopefully it explains the situation Finally, I will send my version of searching.c in a follow-up email. It has a new method: static int32_t dvdnav_jump_to_sector_by_time(dvdnav_t *this, uint32_t time_in_pts_ticks); I send it for curiosity/review purposes. If this new proc is acceptable, I will convert to the preferred patching-method for libdvdnav. (I am honestly ignorant of what is involved) Also, please note I am also very new to C programming (I am a C# programmer with some Java). My apologies in advance for the verbose comments/printfs/lack of convention. Let me know if there is anything else. Thanks. ----EXCERPT FROM THREAD---- I used to use the MS DirectDvd library. I believe it's the same library that Windows MediaPlayer uses (the behavior is exactly the same). It does accurate seeking for most dvds, but there are some DVDs (< 5%) that it will fail and give a Division by Zero error (it will freeze the app). By my best analysis, I think DirectDVD uses the timestamps in the VOB PCI pack (c_eltm?) http://dvd.sourceforge.net/dvdinfo/pci_pkt.html. It doesn't seem to use the IFO at all. >From what I've seen, I think this may be the best of all possible approaches. The info in the IFO will be correct for most dvds, but there are some dvds where the time map (VTS_TMAPTI) is corrupt or missing (5% of my collection). I imagine there are some dvds that have similar issues with VTS_VOBU_ADMAP (have not seen any yet). That said, the div-by-zero errors shows that the VOB PCI pack is not always correct (again, about 5% of my collection. some overlap with the prior 5%). However, I think other info in the VOB PCI pack can be used to correct this corruption (vobu_s_ptm; vobu_e_ptm; vobu_se_e_ptm). I'm assuming that DirectDVD simply didn't bother enough to fix them (especially when considering that div-by-zero freezes the app). Unfortunately, scanning the VOB files for this data is a project beyond my current ability/time. So in its place, I devised an approach that uses the IFOs only. It's not ideal, and will probably not work for poorly-authored DVDs. I'm hoping that segment is small (< 1%). For those DVDs, I think there is no other recourse other than to do VOB PCI pack analysis. The IFO approach works as follows: * Try the time_maps (should work for 95% of dvds) - for a given time, find the entry in the time_map table (VTS_TMAPTI) The time_map will break down a pgc into intervals of n seconds. Unfortunately n is generally 4 seconds, so... - lookup the corresponding sectors in the ad_map table (VTS_VOBU_ADMAP) The tmap sectors will produce a range in ad_map of 6 - 10 VOBUs. - do time interpolation over the 6 - 10 to get the time 6 - 10 will be small enough that time interpolation will be accurate * If there is no good time_map, try the ad_map (should work for the remaining 5% of dvds) - for a given time, find the cell in the pgc - get the sector bounds of the cell - lookup the corresponding sectors from the ad_map table (VTS_VOBU_ADMAP) Unfortunately, the ad_map range will be much larger: a few hundred to a few thousand VOBUs. - do time interpoloation over the range time interpolation is not ideal, as the range is very large however, VOBUs are sized between .4 and 1.5 seconds. Within a given cell, they appear to be reasonably consistent (i.e.: VOBUs may hover around 15 frames) * If there is no good ad_map, then just use the cell (same as dvdnav_time_search) - for a given time, find the cell in the pgc - get the sector bounds of the cell - do time interpolation over the sector bounds this will rarely be accurate. It is there to handle the outlyer dvds (< 1%). Here's a specific example for the time_map approach. It tries to find an @sector for a @time of 5 seconds 1. look at VTS_TMAPTI @time_interval = 4 Entries = tmap_idx sector time 0 711 4 1 1776 8 2 2790 12 since 5 seconds is between 4 and 8, @time is between tmap_idx 0 and 1 @sector_bgn = 711 @sector_end = 1776 2. look at VTS_VOBU_ADMAP Entries = vobu sector 0 0 1 43 etc. 9 711 10 831 11 948 12 1080 13 1213 14 1349 15 1493 16 1642 17 1776 @vobu_bgn = 9 @vobu_end = 17 3. interpolate there are 8 vobus between 9 and 17 5 is 1/4 of the way between 4 and 8 1/4 of the way between 9 and 17 is 11 so, @sector = 948 _______________________________________________ DVDnav-discuss mailing list DVDnav-discuss@mplayerhq.hu https://lists.mplayerhq.hu/mailman/listinfo/dvdnav-discuss