Permalink
Browse files

adds the ability to play a specific title on a DVD or BluRay from fil…

…ename

dvdname.titNN.iso will play title NN (playlist NNNNN.mpls on BR)
a ttile in a DVD folder can be played with
DVDname.titNN/VIDEO_TS/VIDEO_TS.IFO in particular a set of links
DVDname.titNN -> DVD/VIDEO_TS/VIDEO_TS
  • Loading branch information...
1 parent b061d5b commit 6399b48544ae143deef414e722a00eaf9556b365 @dragonflight committed Nov 5, 2012
@@ -274,13 +274,25 @@ BLURAY_TITLE_INFO* CDVDInputStreamBluray::GetTitleFile(const std::string& filena
bool CDVDInputStreamBluray::Open(const char* strFile, const std::string& content)
{
+ int title = 100000;
if(m_player == NULL)
return false;
+ CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::Open - opening %s", strFile);
CStdString strPath(strFile);
CStdString filename;
CStdString root;
+ int iPos = strPath.ReverseFind('?');
+ if( iPos > 0
+ && iPos > strPath.ReverseFind('/')
+ && iPos > strPath.ReverseFind('\\')
+ && strPath.Mid(iPos,7).CompareNoCase("?title") )
+ {
+ title = atoi( strPath.Mid(iPos+7).c_str());
+ strPath = strPath.Left(iPos);
+ }
+
@jmarshallnz
jmarshallnz Nov 5, 2012

Use CURL to parse the URL, then just grab out the URL option directly?

@dragonflight
dragonflight Nov 5, 2012 Owner

I thought of that, tried it, but something about the way options worked didn't. I will look at it again and either remember why I didn't do it or do it

if(strPath.Left(7).Equals("bluray:"))
{
CURL url(strPath);
@@ -289,6 +301,7 @@ bool CDVDInputStreamBluray::Open(const char* strFile, const std::string& content
}
else
{
+ filename = URIUtils::GetFileName(strPath);
URIUtils::GetDirectory(strPath,strPath);
URIUtils::RemoveSlashAtEnd(strPath);
@@ -304,7 +317,6 @@ bool CDVDInputStreamBluray::Open(const char* strFile, const std::string& content
URIUtils::RemoveSlashAtEnd(strPath);
}
root = strPath;
- filename = URIUtils::GetFileName(strFile);
}
@dragonflight
dragonflight Nov 5, 2012 Owner

Because before my changes strPath and strFile were the same, but now strPath is strFile without the optional ?title.
The move to the top is because strPath gets modifed in the middle

if (!m_dll)
@@ -315,7 +327,11 @@ bool CDVDInputStreamBluray::Open(const char* strFile, const std::string& content
m_dll->bd_set_debug_handler(DllLibbluray::bluray_logger);
m_dll->bd_set_debug_mask(DBG_CRIT | DBG_BLURAY | DBG_NAV);
- CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::Open - opening %s", root.c_str());
+ if( title == 100000 )
+ CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::Open - opening %s, %s", root.c_str(), filename.c_str());
+ else
+ CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::Open - opening %s, %s title=%d", root.c_str(), filename.c_str(), title);
+
m_bd = m_dll->bd_open(root.c_str(), NULL);
if(!m_bd)
@@ -366,7 +382,10 @@ bool CDVDInputStreamBluray::Open(const char* strFile, const std::string& content
if(filename.Equals("index.bdmv"))
{
m_navmode = false;
- m_title = GetTitleLongest();
+ if( title >= 100000 || title == 0 )
@jmarshallnz
jmarshallnz Nov 5, 2012

perhaps default title to 0 ?

@dragonflight
dragonflight Nov 5, 2012 Owner

I wanted to differentiate between doing nothing or choosing the longest. in the case of BR they are the same (today), but in the case of DVDs it would be the difference between playing the menu or playing the longest title (which I haven't implemented)

+ m_title = GetTitleLongest();
+ else
+ m_title = m_dll->bd_get_playlist_info(m_bd, abs(title), 0);
@jmarshallnz
jmarshallnz Nov 5, 2012

can title be negative?

@dragonflight
dragonflight Nov 5, 2012 Owner

I missed this change. I originally used negative titles to disable my attempt to decide when the title was finished playing, but after playing with this the last month it seems to always (knock on wood) work so I removed it for this submit, so no it shouldn't be negative

}
else if(URIUtils::GetExtension(filename).Equals(".mpls"))
{
@@ -52,6 +52,7 @@ CDVDInputStreamNavigator::CDVDInputStreamNavigator(IDVDPlayer* player) : CDVDInp
m_bEOF = false;
m_icurrentGroupId = 0;
m_lastevent = DVDNAV_NOP;
+ m_bFinishedPGC = false;
memset(m_lastblock, 0, sizeof(m_lastblock));
}
@@ -64,6 +65,7 @@ CDVDInputStreamNavigator::~CDVDInputStreamNavigator()
bool CDVDInputStreamNavigator::Open(const char* strFile, const std::string& content)
{
char* strDVDFile;
+ int start_title = 100000;
m_icurrentGroupId = 0;
if (!CDVDInputStream::Open(strFile, "video/x-dvd-mpeg"))
return false;
@@ -83,6 +85,12 @@ bool CDVDInputStreamNavigator::Open(const char* strFile, const std::string& cont
// at least one path separator character.
strDVDFile = strdup(strFile);
+ char *p = rindex(strDVDFile, '?');
+ if( p && strncasecmp( p, "?title=", 7) == 0 )
+ {
+ start_title = atoi( p+7 );
+ *p = 0;
+ }
int len = strlen(strDVDFile);
if(len >= 13 // +1 on purpose, to include a separator char before the searched string
@@ -94,6 +102,16 @@ bool CDVDInputStreamNavigator::Open(const char* strFile, const std::string& cont
&& strncasecmp(strDVDFile + len - 8, "VIDEO_TS", 8) == 0)
strDVDFile[len - 9] = '\0';
+ len = strlen(strDVDFile);
+ if( start_title < 100000 )
+ ;
+ else if(len >= 6 // .TITNN
+ && strncasecmp(strDVDFile + len - 6, ".TIT", 4) == 0)
+ start_title = atoi( strDVDFile + len - 2 );
+ else if(len >= 6 // .TRKNN // historical reasons
+ && strncasecmp(strDVDFile + len - 6, ".TRK", 4) == 0)
+ start_title = atoi( strDVDFile + len - 2 );
+
#if defined(TARGET_DARWIN_OSX)
// if physical DVDs, libdvdnav wants "/dev/rdiskN" device name for OSX,
// strDVDFile will get realloc'ed and replaced IF this is a physical DVD.
@@ -185,8 +203,29 @@ bool CDVDInputStreamNavigator::Open(const char* strFile, const std::string& cont
return false;
}
+ m_iTitle = m_iTitleCount = 0;
+ m_iPart = m_iPartCount = 0;
+ m_iTime = m_iTotalTime = 0;
+ m_iPlayTitle = 0;
+
+ if( start_title < 100000 )
+ {
+ int len, event, parts;
+ uint8_t buf[2048];
+ uint8_t* buf_ptr = buf;
+ CLog::Log(LOGDEBUG, "*************** setting title to %d", start_title);
+ m_iTitle = start_title;
+ m_iPlayTitle = start_title;
+ m_iPlayTitleTotalTime = 0;
+ // m_dll.dvdnav_part_play(m_dvdnav, 0, 1);
+ m_dll.dvdnav_part_play(m_dvdnav, m_iTitle, 1);
+ // these all get fixed up in DVDNAV_CELL_CHANGE
+ m_iTitleCount = 0;
+ m_iPart = m_iPartCount = 0;
+ m_iTime = m_iTotalTime = 0;
+ }
// jump directly to title menu
- if(g_guiSettings.GetBool("dvds.automenu"))
+ else if(g_guiSettings.GetBool("dvds.automenu"))
{
int len, event;
uint8_t buf[2048];
@@ -208,9 +247,6 @@ bool CDVDInputStreamNavigator::Open(const char* strFile, const std::string& cont
m_iVobUnitCorrection = 0LL;
m_bInMenu = false;
m_holdmode = HOLDMODE_NONE;
- m_iTitle = m_iTitleCount = 0;
- m_iPart = m_iPartCount = 0;
- m_iTime = m_iTotalTime = 0;
return true;
}
@@ -464,9 +500,16 @@ int CDVDInputStreamNavigator::ProcessBlock(BYTE* dest_buffer, int* read)
m_iCellStart = cell_change_event->cell_start; // store cell time as we need that for time later
m_iTime = (int) (m_iCellStart / 90);
m_iTotalTime = (int) (cell_change_event->pgc_length / 90);
+ if( m_iTitle == m_iPlayTitle )
+ m_iPlayTitleTotalTime = m_iTotalTime;
m_icurrentGroupId = cell_change_event->pgN * 1000 + cell_change_event->cellN;
- iNavresult = m_pDVDPlayer->OnDVDNavResult(buf, DVDNAV_CELL_CHANGE);
+ if( m_iPlayTitle && m_bFinishedPGC ) {
+ m_bEOF = true;
+ iNavresult = m_pDVDPlayer->OnDVDNavResult(buf, DVDNAV_STOP);
+ }
+ else
+ iNavresult = m_pDVDPlayer->OnDVDNavResult(buf, DVDNAV_CELL_CHANGE);
}
break;
@@ -516,6 +559,10 @@ int CDVDInputStreamNavigator::ProcessBlock(BYTE* dest_buffer, int* read)
CLog::Log(LOGDEBUG, "DVDNAV_NAV_PACKET - DISCONTINUITY FROM:%"PRId64" TO:%"PRId64" DIFF:%"PRId64, (m_iVobUnitStop * 1000)/90, ((int64_t)pci->pci_gi.vobu_s_ptm*1000)/90, (gap*1000)/90);
}
+ if( m_iTitle == m_iPlayTitle && pci->pci_gi.vobu_e_ptm/90 >= m_iTotalTime-1 )
+ {
+ m_bFinishedPGC = true;
+ }
m_iVobUnitStart = pci->pci_gi.vobu_s_ptm;
m_iVobUnitStop = pci->pci_gi.vobu_e_ptm;
@@ -154,6 +154,7 @@ class CDVDInputStreamNavigator
int m_iTotalTime;
int m_iTime;
+ bool m_bFinishedPGC;
int64_t m_iCellStart; // start time of current cell in pts units (90khz clock)
bool m_bInMenu;
@@ -164,7 +165,8 @@ class CDVDInputStreamNavigator
int m_iTitleCount;
int m_iTitle;
-
+ int m_iPlayTitle;
+ int m_iPlayTitleTotalTime;
int m_iPartCount;
int m_iPart;
@@ -557,6 +557,8 @@ bool CDVDPlayer::OpenInputStream()
{
m_filename = g_mediaManager.TranslateDevicePath("");
}
+
+ int title = 100000;
retry:
// before creating the input stream, if this is an HLS playlist then get the
// most appropriate bitrate based on our network settings
@@ -579,18 +581,34 @@ bool CDVDPlayer::OpenInputStream()
else
m_pInputStream->SetFileItem(m_item);
- if (!m_pInputStream->Open(m_filename.c_str(), m_mimetype))
+ if( title >= 100000 ) // match filename.titnnn.iso
+ {
+ int t, n=-1, len;
+ char *p, *q;
+ p = strdup(m_filename.c_str());
+ len = strlen( p );
+ if( len > 4 && strcasecmp(&p[len-4], ".iso" ) == 0 )
+ {
+ p[len-4] = 0;
+ if( (q = rindex(p, '.'))
+ && strcasecmp( q, ".tit" )
+ && sscanf( q+4, "%d%n", &t, &n ) >= 1
+ && q[n+4] == 0 )
+ title = t;
+ }
+ free( p );
+ }
+ if( title < 100000 )
+ filename.AppendFormat("?title=%d",title);
+
+ if (!m_pInputStream->Open(filename.c_str(), m_mimetype))
{
if(m_pInputStream->IsStreamType(DVDSTREAM_TYPE_DVD))
{
CLog::Log(LOGERROR, "CDVDPlayer::OpenInputStream - failed to open [%s] as DVD ISO, trying Bluray", m_filename.c_str());
m_mimetype = "bluray/iso";
filename = m_filename;
filename = filename + "/BDMV/index.bdmv";
- int title = (int)m_item.GetProperty("BlurayStartingTitle").asInteger();
- if( title )
- filename.AppendFormat("?title=%d",title);
-
m_filename = filename;
goto retry;
}

0 comments on commit 6399b48

Please sign in to comment.