GNOME Bugzilla – Bug 372797
Seek on DVD not performed relative to title
Last modified: 2011-10-29 04:08:51 UTC
I hope I'm not filing a duplicate, but I can't find reports that seem to be about this problem. This easiest way to reproduce this to use totem on a DVD with at least 2 decent length titles: 1) totem dvd://2 2) Do a seek of decent length 3) I get bumped back into title 1 (which is the general problem... seeks are always getting performed relative to title 1, even when title > 1). I have the same problem creating thumbnails of each title with the DVD ripper I've been working on. Interestingly, I've noticed that on a dual layer disc with several titles, toward the end the seeks will start being performed relative not to the 1st title but relative to some higher number title, which might have something to do with the layer boundary. If anyone has any ideas of where to look, what the problem might be, I'm all ears. Otherwise I'll keep plodding along on my own. ;) I'm running Ubunty Edgy, gst-plugins-ugly 0.10.4 Thanks!
Here is some choice debugging output from a seek to 25% on 4 titles. Each title is approximately 45 minutes. Assuming "sector" here means what it usually would, it looks like the problem is maybe is in gst_dvd_read_src_get_sector_from_time(), as it obviously isn't taking the title into account. There are 13 titles on this DVD Title 1 has 16 chapters Requested seek to time 0:11:05.500000000 Seek to time: 665500000000 Seeking to time: 665500000000 Time 0:11:05.500000000 => sector 257432 Seek succeeded, going to chapter 5, cell 4 There are 13 titles on this DVD Title 2 has 16 chapters Requested seek to time 0:11:03.500000000 Seek to time: 663500000000 Seeking to time: 663500000000 Time 0:11:03.500000000 => sector 256654 Seek succeeded, going to chapter 5, cell 5 There are 13 titles on this DVD Title 3 has 16 chapters Requested seek to time 0:11:00.250000000 Seek to time: 660250000000 Seeking to time: 660250000000 Time 0:11:00.250000000 => sector 256044 Seek succeeded, going to chapter 4, cell 4 There are 13 titles on this DVD Title 4 has 16 chapters Requested seek to time 0:11:12.250000000 Seek to time: 672250000000 Seeking to time: 672250000000 Time 0:11:12.250000000 => sector 260294 Seek succeeded, going to chapter 6, cell 6
Have you tried CVS yet? FWIW, I also have some local patches to enable TIME-based seeking, but I need to clean those up a bit first.
Tim, I pulled just dvdreadsrc.[h,c] from CVS as I'm trying to work out a patch for Edgy, but that didn't solve it. So there have been problems that you've had with time-based seeking also? It seems like querying the position and duration in the sector format is working correctly, so I guess as a stop gap I just do sector-based seeking, and do my own crude time => sector conversion if need be. Thanks!
Hmmm, scratch that. It seems like querying the position and duration in segments only works on the pipeline: dvdreadsrc ! fakesink
Okay, I see what the problems is. It seems that ifoOpen() is loading the tmap for *every* title that has one regardless of the title specified. I'm not sure if that is always the case or just something particular about the DVD's I've been testing (TV serials with several episodes per DVD). So in the iteration through src->vts_tmapt->tmap: for (i = 0; i < src->vts_tmapt->nr_of_tmaps; ++i) { for (j = 0; j < src->vts_tmapt->tmap[i].nr_of_entries; ++j) { ... } } It always finds the correct time in the first title. In the case of this particular DVD, it seems that it might be sufficient to only iterate one deep, through src->vts_tmapt->tmap[src->title], but I don't know if that will work in all cases. Will a single title ever have more than one tmap? So I guess, in the one tmap per title case: * select appropriate tmap (would it always be src->vts_tmapt->tmap[src->title]?) * iterate through tmap.map_ent[] for above tmap And in the multiple tmap per title case: * interate through all tmap, acconting for vts_tmapt->tmap_offset[i] * for each above tmap, iterate through tmap.map_ent[] And as long as I'm at it, it would be much nicer to do all this with an O(log(n)) algorithm, which from what I'm starting to understand about the tmap structures, would be cake. But really, since you know the time unit (vts_tmapt->tmap[i].tmu) and the number of entries, there is really no reason to do any sort of iteration (or binary search) through the tmap, is there? I'll see what I can cook up.
Well, I think this is a correctly functioning implementation of gst_dvd_read_src_get_sector_from_time(). On all the DVDs I've testing it on, it seems to be returning the correct map_ent from the correct tmap. However, seeking still isn't working correctly as there seems to be seek related bugs elsewhere. /* returns the sector in the index at (or before) the given time, or -1 */ static gint gst_dvd_read_src_get_sector_from_time (GstDvdReadSrc * src, GstClockTime ts) { gint i, j; vts_tmap_t tmap; if (src->vts_tmapt == NULL) return -1; i = src->pgc_id - 1; if (!i < src->vts_tmapt->nr_of_tmaps) return -1; tmap = src->vts_tmapt->tmap[i]; j = ts / GST_SECOND / tmap.tmu - 1; if (j < 0) { /* FIXME: we should actually return the start sector for the title */ return tmap.map_ent[0] & 0x7fffffff; } else if (j >= tmap.nr_of_entries) { /* This means we are trying to seek beyond the end time of the current title. */ return tmap.map_ent[tmap.nr_of_entries-1] & 0x7fffffff; } else { return tmap.map_ent[j] & 0x7fffffff; } }
A general issue in dvdreadsrc right now seems to be that it doesn't know how to handle cases where multiple titles will have the same title_set_nr, when DVDOpenFile() and ifoOpen() will be opening the same things for a number of titles. The TV serials with several episodes per DVD that I have been testing have all been setup this way. In this case, the title has to be handled as a segment seek (at least of sorts). For example, a duration query in sector format is answered with DVDFileSize(src->dvd_title), which is wrong in this case because it returns the combined size of *all* the titles on the current title_set_nr; instead it should be (end_sector - start_sector) for the title. Even though I have gst_dvd_read_src_get_sector_from_time() working correctly now, seeking still isn't working correctly because gst_dvd_read_src_goto_sector() seems always to be working from a start a sector 0 rather than the start_sector for the title.
Again, the big problem with dvdreadsrc currently is that it doesn't properly handle cases where the title_set has more than one title. Here's a summary of how things work with libdvdread, as far as I understand: * The title number is mapped to the title_set number with tt_srpt->title[title].title_set_nr * For feature movies, the feature title is usually the only title in its title_set, which is why dvdreadsrc generally worked. But for, say, TV serials with several episodes per DVD, all the episodes usually belong to a single title_set, including the "play all" title that many DVDs have. In these cases, dvdreadsrc is "super extra broken". * ifoOpen and DVDOpenFile take the title_set_nr as an argument; they always open a title_set, not a single title (although as above, for movies the feature title is usually the only title in the title_set). * DVDReadBlocks works relative to the title_set, not the title. A wrong assumption made in many places in dvdreadsrc is that a title always starts at sector zero. In fact, it seems this assumption can't even be made for a title_set with one title. * cell_playback[cell].first_sector and cell_playback[cell].last_sector are relative to the title_set, not the title. This is why, by chance anyway, a multi-title title_set would at least start playing the correct title for title > 0. * If a title_set has a vts_tmapt, it will have exactly one tmap per title in the title_set. As far as I can tell, (tt_srpt->title[title].vts_ttn - 1) gives the index for the correct tmap for the title, but I need someone to verify this. * The times in the tmap are best dealt with relative to the title (which is what we want to do), but the sectors in tmap.map_ent[] are relative to the title_set. This "just works" as long as you are using the correct tmap. In this respect, gst_dvd_read_src_get_sector_from_time() was horibly broken. The original author(s) thought a nested iteration through vts_tmapt->tmap[i].map_ent[j] would somehow give the correct sector, which is utterly wrong, not to mention silly. It seems they got the idea from ifoPrint_VTS_TMAPT(), but didn't take the time to understand the meaning of the data structures. This is part of the reason why seeking is so broken. I have finished a patch that fixes the most glaring title/title_set problems. On large seeks there is still some problem with gst_dvd_read_src_read() and/or gst_dvd_read_src_create() getting caught in an infinite loop and the seek never completing, but I'll look into that later (my patch didn't introduce this problem... it was already happending). Here is a summary of the patch: * Fix gst_dvd_read_src_get_sector_from_time() * Use the correct tmap only instead of iterating through them. I still need someone more familiar with libdvdread to verify that (tt_srpt->title[title].vts_ttn - 1) does indeed always give the index for the correct tmap. * Use "advanced algebra" to select correct map_ent instead of silly iteration. * Fix title starts at sector zero assumption in gst_dvd_read_src_goto_sector(). * Fix title starts at sector zero assumption gst_dvd_read_src_goto_chapter().
Created attachment 76409 [details] [review] fixes several dvdreadsrc title/title_set problems
Comment on attachment 76409 [details] [review] fixes several dvdreadsrc title/title_set problems Here is a summary of the patch: * Fix gst_dvd_read_src_get_sector_from_time() * Use the correct tmap only instead of iterating through them. I still need someone more familiar with libdvdread to verify that (tt_srpt->title[title].vts_ttn - 1) does indeed always give the index for the correct tmap. * Use "advanced algebra" to select correct map_ent instead of silly iteration. * Fix title starts at sector zero assumption in gst_dvd_read_src_goto_sector(). * Fix title starts at sector zero assumption gst_dvd_read_src_goto_chapter().
Created attachment 76456 [details] [review] Improvment on previous patch This improves upon the previous patch. There was no reason to have the member src->vts_tmapt as only the tmap for the current title is needed. So now gst_dvd_read_src_goto_title() sets src->tmap = &src->vts_file->vts_tmapt->tmap[src->ttn-1]... if the title_set has a vts_tmapt (src->vts_file->vts_tmapt != NULL). This allows the code in gst_dvd_read_src_get_sector_from_time() to be cleaned up a bit. I also improved gst_dvd_read_src_get_time_for_sector(). It worked previously because it would eventually find the appropriate sector (if a match was possible). But now it only iterates through the appropriate tmap rather than every tmap in the title_set.
Ah, I did just find a several episode DVD in which each episode title belongs to its own title_set, although from the DVDs I've been testing anyway, this seems to be somewhat rare. My patch works fine in this case (and dvdreadsrc also previously worked in this case too). Trouble was just the assumption that a title_set would *always* have a single title.
I've started writing from scratch a drop in replacement for dvdreadsrc. I'm making sure to write very extensive self-tests so that the assumptions I'm making about how libdvdread works can be verified on many DVDs by many users and developers. Here is the output for a test that mostly checks for tmap to title congruency. It shows the structure of one of those said "multiple titles in a title_set" DVDs. DvdSrc Audit: performing rigorous self-test using current DVD DVD is reporting 8 titles Testing title 1: Title has duration 43:31 Title is reporting 16 chapters Title looks like a feature title (has vts_tmapt) Checking that all chapter_pgc report same title duration Chapter 1 43:31 OKAY Chapter 2 43:31 OKAY Chapter 3 43:31 OKAY Chapter 4 43:31 OKAY Chapter 5 43:31 OKAY Chapter 6 43:31 OKAY Chapter 7 43:31 OKAY Chapter 8 43:31 OKAY Chapter 9 43:31 OKAY Chapter 10 43:31 OKAY Chapter 11 43:31 OKAY Chapter 12 43:31 OKAY Chapter 13 43:31 OKAY Chapter 14 43:31 OKAY Chapter 15 43:31 OKAY Chapter 16 43:31 OKAY Title 1 is in title_set 3 From nr_of_tmaps, title_set appears to have 4 titles Title should be using tmap at index 0 Title has a tmap, index in range: OKAY Tmap has 1305 entries at intervals of 2 seconds Checking time match between tmap and title... Title has duration 43:31 Last tmap entry is at time 43:30 Last_tmap_entry <= title_seconds: OKAY Last_tmap_entry + tmu >= title_seconds: OKAY Tmap and title match on time: OKAY Checking sector match between tmap and title... First sector in title is 0 First sector in tmap is 123 First_tmap_sector >= first_title_sector: OKAY Last sector in title is 968940 Last sector in tmap is 968802 Last_tmap_sector <= last_title_sector: OKAY Tmap and title match on sector: OKAY Finished testing title 1: OKAY Testing title 2: Title has duration 43:09 Title is reporting 16 chapters Title looks like a feature title (has vts_tmapt) Checking that all chapter_pgc report same title duration Chapter 1 43:09 OKAY Chapter 2 43:09 OKAY Chapter 3 43:09 OKAY Chapter 4 43:09 OKAY Chapter 5 43:09 OKAY Chapter 6 43:09 OKAY Chapter 7 43:09 OKAY Chapter 8 43:09 OKAY Chapter 9 43:09 OKAY Chapter 10 43:09 OKAY Chapter 11 43:09 OKAY Chapter 12 43:09 OKAY Chapter 13 43:09 OKAY Chapter 14 43:09 OKAY Chapter 15 43:09 OKAY Chapter 16 43:09 OKAY Title 2 is in title_set 3 From nr_of_tmaps, title_set appears to have 4 titles Title should be using tmap at index 1 Title has a tmap, index in range: OKAY Tmap has 1294 entries at intervals of 2 seconds Checking time match between tmap and title... Title has duration 43:09 Last tmap entry is at time 43:08 Last_tmap_entry <= title_seconds: OKAY Last_tmap_entry + tmu >= title_seconds: OKAY Tmap and title match on time: OKAY Checking sector match between tmap and title... First sector in title is 968941 First sector in tmap is 969312 First_tmap_sector >= first_title_sector: OKAY Last sector in title is 1900575 Last sector in tmap is 1900494 Last_tmap_sector <= last_title_sector: OKAY Tmap and title match on sector: OKAY Finished testing title 2: OKAY Testing title 3: Title has duration 44:28 Title is reporting 16 chapters Title looks like a feature title (has vts_tmapt) Checking that all chapter_pgc report same title duration Chapter 1 44:28 OKAY Chapter 2 44:28 OKAY Chapter 3 44:28 OKAY Chapter 4 44:28 OKAY Chapter 5 44:28 OKAY Chapter 6 44:28 OKAY Chapter 7 44:28 OKAY Chapter 8 44:28 OKAY Chapter 9 44:28 OKAY Chapter 10 44:28 OKAY Chapter 11 44:28 OKAY Chapter 12 44:28 OKAY Chapter 13 44:28 OKAY Chapter 14 44:28 OKAY Chapter 15 44:28 OKAY Chapter 16 44:28 OKAY Title 3 is in title_set 3 From nr_of_tmaps, title_set appears to have 4 titles Title should be using tmap at index 2 Title has a tmap, index in range: OKAY Tmap has 1334 entries at intervals of 2 seconds Checking time match between tmap and title... Title has duration 44:28 Last tmap entry is at time 44:28 Last_tmap_entry <= title_seconds: OKAY Last_tmap_entry + tmu >= title_seconds: OKAY Tmap and title match on time: OKAY Checking sector match between tmap and title... First sector in title is 1900576 First sector in tmap is 1900643 First_tmap_sector >= first_title_sector: OKAY Last sector in title is 2867463 Last sector in tmap is 2867459 Last_tmap_sector <= last_title_sector: OKAY Tmap and title match on sector: OKAY Finished testing title 3: OKAY Testing title 4: Title has duration 42:51 Title is reporting 16 chapters Title looks like a feature title (has vts_tmapt) Checking that all chapter_pgc report same title duration Chapter 1 42:51 OKAY Chapter 2 42:51 OKAY Chapter 3 42:51 OKAY Chapter 4 42:51 OKAY Chapter 5 42:51 OKAY Chapter 6 42:51 OKAY Chapter 7 42:51 OKAY Chapter 8 42:51 OKAY Chapter 9 42:51 OKAY Chapter 10 42:51 OKAY Chapter 11 42:51 OKAY Chapter 12 42:51 OKAY Chapter 13 42:51 OKAY Chapter 14 42:51 OKAY Chapter 15 42:51 OKAY Chapter 16 42:51 OKAY Title 4 is in title_set 3 From nr_of_tmaps, title_set appears to have 4 titles Title should be using tmap at index 3 Title has a tmap, index in range: OKAY Tmap has 1285 entries at intervals of 2 seconds Checking time match between tmap and title... Title has duration 42:51 Last tmap entry is at time 42:50 Last_tmap_entry <= title_seconds: OKAY Last_tmap_entry + tmu >= title_seconds: OKAY Tmap and title match on time: OKAY Checking sector match between tmap and title... First sector in title is 2867464 First sector in tmap is 2867525 First_tmap_sector >= first_title_sector: OKAY Last sector in title is 3819706 Last sector in tmap is 3819597 Last_tmap_sector <= last_title_sector: OKAY Tmap and title match on sector: OKAY Finished testing title 4: OKAY Testing title 5: Title has duration 42:51 Title is reporting 2 chapters Title does not looks like a feature title (no vts_tmapt) No usefull tests to do on this title... Testing title 6: Title has duration 42:51 Title is reporting 3 chapters Title does not looks like a feature title (no vts_tmapt) No usefull tests to do on this title... Testing title 7: Title has duration 42:51 Title is reporting 2 chapters Title does not looks like a feature title (no vts_tmapt) No usefull tests to do on this title... Testing title 8: Title has duration 0:00 Title is reporting 1 chapters Title looks like a feature title (has vts_tmapt) Checking that all chapter_pgc report same title duration Chapter 1 0:00 OKAY Title 8 is in title_set 1 From nr_of_tmaps, title_set appears to have 1 titles Title should be using tmap at index 0 Title has a tmap, index in range: OKAY Tmap has 1 entries at intervals of 1 seconds Title_seconds <= 0, not checking match between tmap and title DvdSrc Audit: OKAY
Created attachment 76697 [details] test-dvdreadsrc.c Cool stuff, thanks for looking into all this! I also wrote some test routines for dvdreadsrc, file attached. Works only with my locally modified version that operates completely TIME-format based, but you might find useful bits in there.
Tim, Thanks for the code. The rewrite I'm working on also operates strictly in FORMAT_TIME. The more I learn about libdvdread, the more I realize how difficult it is to give meaningful answers to position or duration queries in sectors or bytes. But there is really no need to... dvdreadsrc is a push mode source for a reason. In its real world usage only FORMAT_TIME is of interest, so the other cruft might as well be removed. On that note I have a question for you: is there any reason that a push source need to be able to handle a GST_QUERY_CONVERT query? I my tests with Totem, Thoggen, and KungFu, gst_dvd_read_src_do_convert_query() is never getting called. I guess in particular, is there any reason that dvdreadsrc needs handle GST_QUERY_CONVERT queries, in terms of what dvddemux and mpeg2dec expect? Cheers!
> ... In its real world usage only FORMAT_TIME is of interest, > so the other cruft might as well be removed. > > On that note I have a question for you: is there any reason that a push source > need to be able to handle a GST_QUERY_CONVERT query? I my tests with Totem, > Thoggen, and KungFu, gst_dvd_read_src_do_convert_query() is never getting > called. I guess in particular, is there any reason that dvdreadsrc needs > handle GST_QUERY_CONVERT queries, in terms of what dvddemux and mpeg2dec > expect? Three reasons as far as I can see: - dvdreadsrc should be able to handle seeks in BYTE format for reasons of backwards compatibility. This does not affect your new differently-named element of course. - GstBaseSrc will attempt a conversion to TIME when it gets a seek in a non-TIME format. This includes things like a seek in chapter format to a specific chapter (we don't have an interface for this kind of stuff, so we're stuck doing this via a seek at the moment). - an application might want to know an approximate time offset for a certain chapter (although I don't know of any apps that use something like this yet, besides the above test case).
> - GstBaseSrc will attempt a conversion to TIME when it gets a > seek in a non-TIME format. This is assuming the source operates in TIME format.
Tim, Thanks for the advice. Regardless how it happens, I'd really like there to be a bombproof DVD-reading plugin in GStreamer so that Totem, Thoggen, KungFu, and whatever else, aren't held back by the plugin. What is your advice on making this happen, hopefully for gst-plugins-ugly 0.10.5? The code I've been working on is in a Bazzar repository on Launchpad: https://launchpad.net/people/jderose/+branch/kungfu/dvdsrc And one more quick question, if you don't mind. In your experience, what have been some especially tricky DVDs that have caused problems for dvdreadsrc or Thoggen in the past, especially multi-angle DVDs? Thanks!
Tim, I've found some DVDs where the final cell in the title is located in sectors before the first cell of the title, and this final cell has a duration of 0. I need to investigate some more, but I believe this final cell might be Nav related, used to put the menu into a different state based upon what title just finish playing. Any ideas on how this should be handled? Should whatever packets exist in this last cell be passed to dvddemux, or should the EOS event be sent as soon as this last cell is reached? Here is an example of what I'm talking about, from Kill Bill Volume 2: Title 001 time: 02:16.000000048, sector_range: 0000000004 - 0000000003 Cell 000 time: 00:01.000000059, sector_range: 0000000004 - 0000035899 Cell 001 time: 00:03.000000027, sector_range: 0000035900 - 0000123559 Cell 002 time: 00:09.000000022, sector_range: 0000123560 - 0000354174 Cell 003 time: 00:03.000000017, sector_range: 0000354175 - 0000427178 Cell 004 time: 00:04.000000044, sector_range: 0000427179 - 0000539606 Cell 005 time: 00:08.000000002, sector_range: 0000539607 - 0000698160 Cell 006 time: 00:08.000000017, sector_range: 0000698161 - 0000836438 Cell 007 time: 00:18.000000019, sector_range: 0000836439 - 0001307818 Cell 008 time: 00:05.000000033, sector_range: 0001307819 - 0001424729 Cell 009 time: 00:11.000000034, sector_range: 0001424730 - 0001673721 Cell 010 time: 00:06.000000031, sector_range: 0001673722 - 0001829109 Cell 011 time: 00:06.000000034, sector_range: 0001829110 - 0001983948 Cell 012 time: 00:04.000000026, sector_range: 0001983949 - 0002073913 Cell 013 time: 00:07.000000052, sector_range: 0002073914 - 0002256581 Cell 014 time: 00:09.000000027, sector_range: 0002256582 - 0002465605 Cell 015 time: 00:05.000000036, sector_range: 0002465606 - 0002587115 Cell 016 time: 00:06.000000056, sector_range: 0002587116 - 0002723329 Cell 017 time: 00:01.000000054, sector_range: 0002723330 - 0002764125 Cell 018 time: 00:12.000000052, sector_range: 0002764126 - 0003054732 Cell 019 time: 00:00.000000000, sector_range: 0000000000 - 0000000003
Oops, I was my time format was missing the hour, but otherwise it was correct: Title 001 time: 2:16:48.000000000, sector_range: 0000000004 - 0000000003 Cell 000 time: 0:01:59.000000000, sector_range: 0000000004 - 0000035899 Cell 001 time: 0:03:27.000000000, sector_range: 0000035900 - 0000123559 Cell 002 time: 0:09:22.000000000, sector_range: 0000123560 - 0000354174 Cell 003 time: 0:03:17.000000000, sector_range: 0000354175 - 0000427178 Cell 004 time: 0:04:44.000000000, sector_range: 0000427179 - 0000539606 Cell 005 time: 0:08:02.000000000, sector_range: 0000539607 - 0000698160 Cell 006 time: 0:08:17.000000000, sector_range: 0000698161 - 0000836438 Cell 007 time: 0:18:19.000000000, sector_range: 0000836439 - 0001307818 Cell 008 time: 0:05:33.000000000, sector_range: 0001307819 - 0001424729 Cell 009 time: 0:11:34.000000000, sector_range: 0001424730 - 0001673721 Cell 010 time: 0:06:31.000000000, sector_range: 0001673722 - 0001829109 Cell 011 time: 0:06:34.000000000, sector_range: 0001829110 - 0001983948 Cell 012 time: 0:04:26.000000000, sector_range: 0001983949 - 0002073913 Cell 013 time: 0:07:52.000000000, sector_range: 0002073914 - 0002256581 Cell 014 time: 0:09:27.000000000, sector_range: 0002256582 - 0002465605 Cell 015 time: 0:05:36.000000000, sector_range: 0002465606 - 0002587115 Cell 016 time: 0:06:56.000000000, sector_range: 0002587116 - 0002723329 Cell 017 time: 0:01:54.000000000, sector_range: 0002723330 - 0002764125 Cell 018 time: 0:12:52.000000000, sector_range: 0002764126 - 0003054732 Cell 019 time: 0:00:00.000000000, sector_range: 0000000000 - 0000000003
Is this bug still valid now that we have the resin plugin ?
I think it's still useful behaviour for dvdreadsrc to support - useful for thoggen, for example.
Likely fixed by https://bugzilla.gnome.org/show_bug.cgi?id=659252, can you please check ?
Please feel free to reopen this bug if the problem still occurs with a newer version of gstreamer.