[WINDOWS] bluray support selects wrong playlist
#1
Question 
Hello,

I've been using XBMC nightly builds since they were re-enabled back around January 2011ish specifically for playing back unencrypted bdiso files.

It's been working great and support for bluray keeps improving, but I have noticed on certain movies the wrong playlist is loaded (and typically plays a commentary version of the playlist instead) I've only seen this happen on a handful of movies.

For example X-Men First Class (2011) should play BDMV\PLAYLIST\00800.mpls which is the cinema main film version, but instead it plays BDMV\PLAYLIST\00500.mpls which is the main film interlaced with commentary clips and voice overs

It doesn't happen on all movies only certain ones, another example is The Silence of the Lambs (1991).

I wanted to try and debug this myself so I downloaded the latest copy of the XBMC source from git "xbmc-xbmc-c051742" and compiled my own debug copy in VS2010

I also re-ordered some lines in DVDInputStreamBluray.cpp so that the debug log would be more human readable and not curled/formatted

Code:
CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - Opening udf dir %s...", strDirname.c_str());
      CURL::Encode(strDirname);
      strDirname.Format("udf://%s", strDirname);

Here is my xbmc debug log http://pastebin.com/m3L1RMMX you can see one of the last playlists it reads is 00500.mpls

I was trying to debug this further and I figured that the core logic which is where the issue could be is likely to be in libbluray, so I tried to re-compile my own windows binary of that using the git source on videolan but for whatever reason (due to libxml2 which is installed even though it says it's not) it wouldn't compile under cygwin.

So I'm kind of stuck at the moment and was wondering if this is a known issue or something like that?
Reply
#2
just the nature of heuristics. in this particular case the logic is very simple, and easily flawed; 'play the longest playlist'.
Reply
#3
spiff Wrote:just the nature of heuristics. in this particular case the logic is very simple, and easily flawed; 'play the longest playlist'.

That actually makes a lot of sense, and it's probably doing this because there is no bluray menu support and there needs to be a way to find the main film playlist without user interaction right?

I assume this means it's an issue in XBMC and not libbluray right? Could you point me to a file/function where the brunt of that heuristics is happening please?

There might not be a way of easily solving this, but at least I might be able to make a workaround sort of like reading an Edit Decision List, maybe it could look for a firstplay.xbmc text file that contains a path to a playlist/m2ts
Reply
#4
correct on the reason. see xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamBluray.cpp
Reply
#5
spiff Wrote:correct on the reason. see xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamBluray.cpp

Thanks spiff

I was able to change some code in
Code:
CDVDInputStreamBluray::Open

To make a temp fix. I noticed that playlist 800 wasn't returned by TITLES_RELEVANT and in testing i found that playlist 850 worked the same (duplicate playlist for some reason). But I changed the code to TITLES_ALL so I could load any title/playlist I wanted.

The following code works for selecting a specific playlist. This could be used to make a over-ride of the default logic if a over-ride file is present or something to that effect.

Code:
CStdString filename = URIUtils::GetFileName(strFile);
  if(filename.Equals("index.bdmv"))
  {
    CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::Open - processing index.bdmv");
    //int titles = m_dll->bd_get_titles(m_bd, TITLES_RELEVANT, 0);
    int titles = m_dll->bd_get_titles(m_bd, TITLES_ALL, 0);

    BLURAY_TITLE_INFO *t, *s = NULL;
    for(int i=0; i < titles; i++)
    {
      t = m_dll->bd_get_title_info(m_bd, i, 0);
      if(!t)
      {
        CLog::Log(LOGDEBUG, "get_main_title - unable to get title %d", i);
        continue;
      } else {
        CLog::Log(LOGDEBUG, "get_main_title - title %d", i);
      }
      /*
      if(!s || s->duration < t->duration)
        std::swap(s, t);
     */

      if(t->playlist == 800)
      {
          m_title = t;
      }

      CLog::Log(LOGDEBUG, "get_main_title - playlist %d", t->playlist);

     //if(t)
     //  m_dll->bd_free_title_info(t);
    }
    //m_title = s;


  }
  else if(URIUtils::GetExtension(filename).Equals(".mpls"))

playlist selection occurs at this line above, I'm hard coding 800 in this example for playlist 00800.mpls
if(t->playlist == 800)
Reply
#6
Would it make sense to (at some point add code to) pop up a dialog that asks which of the playlists found from BDMV should be played? That would bring quite a lot of improvement in usability, IMO.
Reply
#7
WhiningKhan Wrote:Would it make sense to (at some point add code to) pop up a dialog that asks which of the playlists found from BDMV should be played? That would bring quite a lot of improvement in usability, IMO.

Yeah I was actually thinking the same thing, I have modified the code to look for a firstplay.xbmc file first (name needs to change to the isoname.firstplay or something but this will do for now) and when trying to override a playlist I wasn't sure which ones I should choose from.

I added some logging to the code when a new longest playlist was found and what the old longest playlist was. This logic could be used to display a dialog with a list of playlists where the longest playlists are at the top and the shortest are at the bottom.

Code:
if(URIUtils::GetFileName(strPath) == "PLAYLIST")
  {
    URIUtils::GetDirectory(strPath,strPath);
    URIUtils::RemoveSlashAtEnd(strPath);
  }

  if(URIUtils::GetFileName(strPath) == "BDMV")
  {
    URIUtils::GetDirectory(strPath,strPath);
    URIUtils::RemoveSlashAtEnd(strPath);
  }
  CStdString strSearchPath;
  URIUtils::GetDirectory(strPath,strSearchPath);
  strSearchPath += "firstplay.xbmc";

  CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::Open - search path %s", strSearchPath.c_str());

  int iFirstPlaylist;
  iFirstPlaylist = -1;
  if (CFile::Exists(strSearchPath, false)) {
        if(URIUtils::IsSmb(strSearchPath)) {
            string strNeedle;
            strNeedle = "smb://";
            strSearchPath = strSearchPath.replace(0, strNeedle.size(), "\\\\");
            strNeedle = "/";
            strSearchPath = strSearchPath.replace(0, strNeedle.size(), "\\");
        }

        ifstream fpFile(strSearchPath);
        string strFirstPlay;
        getline(fpFile, strFirstPlay);

        CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::Open - firstplay: %s", strFirstPlay.c_str());

        sscanf(strFirstPlay.c_str(), "%05d.mpls", &iFirstPlaylist);
  }


  if (!m_dll)
    return false;

  m_dll->bd_register_dir(DllLibbluray::dir_open);
  m_dll->bd_register_file(DllLibbluray::file_open);
#ifndef HAVE_LIBBLURAY_NOLOGCONTROL
  m_dll->bd_set_debug_handler(DllLibbluray::bluray_logger);
  m_dll->bd_set_debug_mask(DBG_CRIT);
#endif

  CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::Open - opening %s", strPath.c_str());
  m_bd = m_dll->bd_open(strPath.c_str(), NULL);

  if(!m_bd)
  {
    CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - failed to open %s", strPath.c_str());
    return false;
  }

  CStdString filename = URIUtils::GetFileName(strFile);
  if(filename.Equals("index.bdmv"))
  {
    CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::Open - processing index.bdmv");
    int titles = 0;
    if(iFirstPlaylist > -1) {
        titles = m_dll->bd_get_titles(m_bd, TITLES_ALL, 0);
    } else {
        titles = m_dll->bd_get_titles(m_bd, TITLES_RELEVANT, 0);
    }

    BLURAY_TITLE_INFO *t, *s = NULL;
    for(int i=0; i < titles; i++)
    {
      t = m_dll->bd_get_title_info(m_bd, i, 0);
      if(!t)
      {
        CLog::Log(LOGDEBUG, "get_main_title - unable to get title %d", i);
        continue;
      } else {
        CLog::Log(LOGDEBUG, "get_main_title - title %d", i);
      }
      
      if(iFirstPlaylist > -1) {
        if(t->playlist == iFirstPlaylist) {
          m_title = t;
        }
      } else {
        if(!s || s->duration < t->duration) {
            if(s) {
                CLog::Log(LOGDEBUG, "get_main_title - old longest playlist: %d", s->playlist);
            }
            if(t) {
                CLog::Log(LOGDEBUG, "get_main_title - new longest playlist: %d", t->playlist);
            }
            std::swap(s, t);
        }

        if(t)
          m_dll->bd_free_title_info(t);
      }
    }
    if(iFirstPlaylist == -1) {
        m_title = s;
    }
    CLog::Log(LOGDEBUG, "get_main_title - loading playlist %d", m_title->playlist);
  }
  else if(URIUtils::GetExtension(filename).Equals(".mpls"))

/edit/
Also the core logic that XBMC does is actually really good in terms of a success rate at finding the film playlist, it's almost always the longest playlist. This dialog that appears could be made to appear only if a choice between the longest playlist was close. So if there's a playlist that's 5mins long and two playlists that are over 1 hour long then this dialog could appear.
Reply
#8
we've been pondering exposing bluray / dvd titles as a vfs. so you'd browse the bluray as a directory, and you'd get a list of titles..
Reply
#9
spiff Wrote:we've been pondering exposing bluray / dvd titles as a vfs. so you'd browse the bluray as a directory, and you'd get a list of titles..

Yes, that might be a bit cleaner than popup menu, IMO; 'play' -operation done to a bluray could just use the 'guess main title'-method and start playing it, while 'browse'-operation (or selecting index.bdmv from 'real' file browser?) could descend into a virtual filesystem view of the bluray content. It would be quite useful.
Reply
#10
Hate to bump this thread but may i ask why it finds the longest playlist? And not the largest file size?

In movies like underworld and blackhawk down its playing the extras because they are 10 minutes longer then the main movie.

The main movie is always the largest file size referenced in the mpls. I dont know if this can be altered from xbmc end or not.
Reply
#11
The main movie is NOT always the largest file size. The Cars bluray is the best example for it. It consists of hundreds of small files, because they also translated strings in the pictures and therefor combine hundreds of small clips for each language, reusing generic clips where possible.
Reply
#12
da-anda Wrote:The main movie is NOT always the largest file size. The Cars bluray is the best example for it. It consists of hundreds of small files, because they also translated strings in the pictures and therefor combine hundreds of small clips for each language, reusing generic clips where possible.

I am aware of small files, incredibles is another one, but the mpls which references those main mt2s files should also explain the combined file size... adding up to a large file size
Reply
#13
Here is the incredibles bdinfo, the mpls file which refrences all those mt2s files contains the file size, and is infact the largest....


00800.mpls the box which i have ticked at the top is the main mpls file which plays all those tiny mt2s streams in the proper order.

It is yet again the largest file size....

Ignore the duplicate mpls entries as those dont matter in this topic, they just are duplicates of that playlist.

Notice the 29gb

You can also see all those tiny mt2s streams in the second area.


http://imageshack.us/f/41/bdinfo.png/


Going by length again does not always work, i just noticed the movie red cliff also plays the extras because its standard definition 4X3 video is a few minutes longer then the main movie.

Here is another one, underworld blu-ray (american version) this one is extreme. XBmc plays the extras because it is exactly 1 single second longer then the main movie. The file size difference however... the main movie playlist file is much larger size wise.

http://imageshack.us/f/109/bdinfo2.png/
Reply
#14
Check the source of DVDFab's XBMC-based player it pops up a window with stream selection - maybe it could be incorporated.

http://forum.xbmc.org/showthread.php?tid=123801&page=3
Reply
#15
Interesting, I will keep my eye on that.

I am all for external players, but i think i made a really good point here on something that could easily be changed to improve xbmc.

its not so much I use xbmc for playback, but its also scrapping cases incorrectly as "Dvd" due to this, I dont think this would be a tough fix, and I feel like I made a valid point of simply using file size rather then movie length.
Reply

Logout Mark Read Team Forum Stats Members Help
[WINDOWS] bluray support selects wrong playlist0