From ba079dc16e90a414e8ef0cd084e0cacb61252871 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Mon, 21 Mar 2016 21:14:08 -0600 Subject: [PATCH] CDVDInputStreamFFmpeg: Moved in CPlayListM3U::GetBestBandwidthStream --- .../DVDInputStreams/DVDInputStreamFFmpeg.cpp | 90 +++++++++++++- .../DVDInputStreams/DVDInputStreamFFmpeg.h | 3 + xbmc/playlists/PlayListM3U.cpp | 113 +++--------------- xbmc/playlists/PlayListM3U.h | 13 +- 4 files changed, 118 insertions(+), 101 deletions(-) diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamFFmpeg.cpp b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamFFmpeg.cpp index fb7797ea53c79..26c6e3cabe69b 100644 --- a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamFFmpeg.cpp +++ b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamFFmpeg.cpp @@ -19,12 +19,18 @@ */ #include "DVDInputStreamFFmpeg.h" + +#include "filesystem/File.h" #include "playlists/PlayListM3U.h" #include "settings/Settings.h" #include "utils/log.h" +#include "utils/StringUtils.h" +#include "utils/URIUtils.h" + #include using namespace XFILE; +using PLAYLIST::CPlayListM3U; CDVDInputStreamFFmpeg::CDVDInputStreamFFmpeg(CFileItem& fileitem) : CDVDInputStream(DVDSTREAM_TYPE_FFMPEG, fileitem) @@ -57,7 +63,7 @@ bool CDVDInputStreamFFmpeg::Open() if(bandwidth <= 0) bandwidth = INT_MAX; const CURL playlist_url = m_item.GetURL(); - const CURL selected = PLAYLIST::CPlayListM3U::GetBestBandwidthStream(playlist_url, bandwidth); + const CURL selected = GetM3UBestBandwidthStream(playlist_url, bandwidth); if (selected.Get() != playlist_url.Get()) { CLog::Log(LOGINFO, "CDVDInputStreamFFmpeg: Auto-selecting %s based on configured bandwidth.", @@ -147,3 +153,85 @@ std::string CDVDInputStreamFFmpeg::GetProxyPassword() const return m_item.HasProperty("proxy.password") ? m_item.GetProperty("proxy.password").asString() : std::string(); } + +CURL CDVDInputStreamFFmpeg::GetM3UBestBandwidthStream(const CURL &url, size_t bandwidth) +{ + typedef CPlayListM3U M3U; + using std::string; + using std::map; + + // we may be passed a playlist that does not contain playlists of different + // bitrates (eg: this playlist is really the HLS video). So, default the + // return to the filename so it can be played + char szLine[4096]; + string strLine; + size_t maxBandwidth = 0; + + // open the file, and if it fails, return + CFile file; + if (!file.Open(url)) + { + file.Close(); + return url; + } + + // and set the fallback value + CURL subStreamUrl(url); + + // determine the base + CURL basePlaylistUrl(URIUtils::GetParentPath(url.Get())); + basePlaylistUrl.SetOptions(""); + basePlaylistUrl.SetProtocolOptions(""); + const string basePart = basePlaylistUrl.Get(); + + // convert bandwidth specified in kbps to bps used by the m3u8 + bandwidth *= 1000; + + while (file.ReadString(szLine, 1024)) + { + // read and trim a line + strLine = szLine; + StringUtils::Trim(strLine); + + // skip the first line + if (strLine == M3U::StartMarker) + continue; + else if (StringUtils::StartsWith(strLine, M3U::StreamMarker)) + { + // parse the line so we can pull out the bandwidth + const map< string, string > params = M3U::ParseStreamLine(strLine); + const map< string, string >::const_iterator it = params.find(M3U::BandwidthMarker); + + if (it != params.end()) + { + const size_t streamBandwidth = atoi(it->second.c_str()); + if ((maxBandwidth < streamBandwidth) && (streamBandwidth <= bandwidth)) + { + // read the next line + if (!file.ReadString(szLine, 1024)) + continue; + + strLine = szLine; + StringUtils::Trim(strLine); + + // this line was empty + if (strLine.empty()) + continue; + + // store the max bandwidth + maxBandwidth = streamBandwidth; + + // if the path is absolute just use it + if (CURL::IsFullPath(strLine)) + subStreamUrl = CURL(strLine); + else + subStreamUrl = CURL(basePart + strLine); + } + } + } + } + + // if any protocol options were set, restore them + subStreamUrl.SetProtocolOptions(url.GetProtocolOptions()); + return subStreamUrl; +} diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamFFmpeg.h b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamFFmpeg.h index 038372836a79e..8f96fd05cbd26 100644 --- a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamFFmpeg.h +++ b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamFFmpeg.h @@ -48,6 +48,9 @@ class CDVDInputStreamFFmpeg std::string GetProxyUser() const; std::string GetProxyPassword() const; +private: + static CURL GetM3UBestBandwidthStream(const CURL &url, size_t bandwidth); + protected: bool m_can_pause; bool m_can_seek; diff --git a/xbmc/playlists/PlayListM3U.cpp b/xbmc/playlists/PlayListM3U.cpp index e934f222cec23..9004c463ac2de 100644 --- a/xbmc/playlists/PlayListM3U.cpp +++ b/xbmc/playlists/PlayListM3U.cpp @@ -22,7 +22,6 @@ #include "filesystem/File.h" #include "URL.h" #include "Util.h" -#include "utils/StringUtils.h" #include "utils/CharsetConverter.h" #include "utils/log.h" #include "utils/URIUtils.h" @@ -32,13 +31,13 @@ using namespace PLAYLIST; using namespace XFILE; -#define M3U_START_MARKER "#EXTM3U" -#define M3U_INFO_MARKER "#EXTINF" -#define M3U_ARTIST_MARKER "#EXTART" -#define M3U_ALBUM_MARKER "#EXTALB" -#define M3U_STREAM_MARKER "#EXT-X-STREAM-INF" -#define M3U_BANDWIDTH_MARKER "BANDWIDTH" -#define M3U_OFFSET_MARKER "#EXT-KX-OFFSET" +const char* CPlayListM3U::StartMarker = "#EXTCPlayListM3U::M3U"; +const char* CPlayListM3U::InfoMarker = "#EXTINF"; +const char* CPlayListM3U::ArtistMarker = "#EXTART"; +const char* CPlayListM3U::AlbumMarker = "#EXTALB"; +const char* CPlayListM3U::StreamMarker = "#EXT-X-STREAM-INF"; +const char* CPlayListM3U::BandwidthMarker = "BANDWIDTH"; +const char* CPlayListM3U::OffsetMarker = "#EXT-KX-OFFSET"; // example m3u file: // #EXTM3U @@ -93,7 +92,7 @@ bool CPlayListM3U::Load(const std::string& strFileName) strLine = szLine; StringUtils::Trim(strLine); - if (StringUtils::StartsWith(strLine, M3U_INFO_MARKER)) + if (StringUtils::StartsWith(strLine, InfoMarker)) { // start of info size_t iColon = strLine.find(":"); @@ -111,7 +110,7 @@ bool CPlayListM3U::Load(const std::string& strFileName) g_charsetConverter.unknownToUTF8(strInfo); } } - else if (StringUtils::StartsWith(strLine, M3U_OFFSET_MARKER)) + else if (StringUtils::StartsWith(strLine, OffsetMarker)) { size_t iColon = strLine.find(":"); size_t iComma = strLine.find(","); @@ -126,9 +125,9 @@ bool CPlayListM3U::Load(const std::string& strFileName) iEndOffset = atoi(strLine.substr(iComma).c_str()); } } - else if (strLine != M3U_START_MARKER && - !StringUtils::StartsWith(strLine, M3U_ARTIST_MARKER) && - !StringUtils::StartsWith(strLine, M3U_ALBUM_MARKER)) + else if (strLine != StartMarker && + !StringUtils::StartsWith(strLine, ArtistMarker) && + !StringUtils::StartsWith(strLine, AlbumMarker)) { std::string strFileName = strLine; @@ -200,7 +199,7 @@ void CPlayListM3U::Save(const std::string& strFileName) const CLog::Log(LOGERROR, "Could not save M3U playlist: [%s]", strPlaylist.c_str()); return; } - std::string strLine = StringUtils::Format("%s\n",M3U_START_MARKER); + std::string strLine = StringUtils::Format("%s\n",StartMarker); if (file.Write(strLine.c_str(), strLine.size()) != static_cast(strLine.size())) return; // error @@ -209,12 +208,12 @@ void CPlayListM3U::Save(const std::string& strFileName) const CFileItemPtr item = m_vecItems[i]; std::string strDescription=item->GetLabel(); g_charsetConverter.utf8ToStringCharset(strDescription); - strLine = StringUtils::Format( "%s:%i,%s\n", M3U_INFO_MARKER, item->GetMusicInfoTag()->GetDuration() / 1000, strDescription.c_str() ); + strLine = StringUtils::Format( "%s:%i,%s\n", InfoMarker, item->GetMusicInfoTag()->GetDuration() / 1000, strDescription.c_str() ); if (file.Write(strLine.c_str(), strLine.size()) != static_cast(strLine.size())) return; // error if (item->m_lStartOffset != 0 || item->m_lEndOffset != 0) { - strLine = StringUtils::Format("%s:%i,%i\n", M3U_OFFSET_MARKER, item->m_lStartOffset, item->m_lEndOffset); + strLine = StringUtils::Format("%s:%i,%i\n", OffsetMarker, item->m_lStartOffset, item->m_lEndOffset); file.Write(strLine.c_str(),strLine.size()); } std::string strFileName = ResolveURL(item); @@ -226,94 +225,16 @@ void CPlayListM3U::Save(const std::string& strFileName) const file.Close(); } -CURL CPlayListM3U::GetBestBandwidthStream(const CURL &url, size_t bandwidth) -{ - // we may be passed a playlist that does not contain playlists of different - // bitrates (eg: this playlist is really the HLS video). So, default the - // return to the filename so it can be played - char szLine[4096]; - std::string strLine; - size_t maxBandwidth = 0; - - // open the file, and if it fails, return - CFile file; - if (!file.Open(url)) - { - file.Close(); - return url; - } - - // and set the fallback value - CURL subStreamUrl(url); - - // determine the base - CURL basePlaylistUrl(URIUtils::GetParentPath(url.Get())); - basePlaylistUrl.SetOptions(""); - basePlaylistUrl.SetProtocolOptions(""); - std::string basePart = basePlaylistUrl.Get(); - - // convert bandwidth specified in kbps to bps used by the m3u8 - bandwidth *= 1000; - - while (file.ReadString(szLine, 1024)) - { - // read and trim a line - strLine = szLine; - StringUtils::Trim(strLine); - - // skip the first line - if (strLine == M3U_START_MARKER) - continue; - else if (StringUtils::StartsWith(strLine, M3U_STREAM_MARKER)) - { - // parse the line so we can pull out the bandwidth - std::map< std::string, std::string > params = ParseStreamLine(strLine); - std::map< std::string, std::string >::iterator it = params.find(M3U_BANDWIDTH_MARKER); - - if (it != params.end()) - { - size_t streamBandwidth = atoi(it->second.c_str()); - if ((maxBandwidth < streamBandwidth) && (streamBandwidth <= bandwidth)) - { - // read the next line - if (!file.ReadString(szLine, 1024)) - continue; - - strLine = szLine; - StringUtils::Trim(strLine); - - // this line was empty - if (strLine.empty()) - continue; - - // store the max bandwidth - maxBandwidth = streamBandwidth; - - // if the path is absolute just use it - if (CURL::IsFullPath(strLine)) - subStreamUrl = CURL(strLine); - else - subStreamUrl = CURL(basePart + strLine); - } - } - } - } - - // if any protocol options were set, restore them - subStreamUrl.SetProtocolOptions(url.GetProtocolOptions()); - return subStreamUrl; -} - std::map< std::string, std::string > CPlayListM3U::ParseStreamLine(const std::string &streamLine) { std::map< std::string, std::string > params; // ensure the line has something beyond the stream marker and ':' - if (streamLine.size() < strlen(M3U_STREAM_MARKER) + 2) + if (streamLine.size() < strlen(StreamMarker) + 2) return params; // get the actual params following the : - std::string strParams(streamLine.substr(strlen(M3U_STREAM_MARKER) + 1)); + std::string strParams(streamLine.substr(strlen(StreamMarker) + 1)); // separate the parameters std::vector vecParams = StringUtils::Split(strParams, ","); diff --git a/xbmc/playlists/PlayListM3U.h b/xbmc/playlists/PlayListM3U.h index 61cee5d55303f..54cf14cc16d3b 100644 --- a/xbmc/playlists/PlayListM3U.h +++ b/xbmc/playlists/PlayListM3U.h @@ -26,16 +26,21 @@ namespace PLAYLIST class CPlayListM3U : public CPlayList { +public: + static const char *StartMarker; + static const char *InfoMarker; + static const char *ArtistMarker; + static const char *AlbumMarker; + static const char *StreamMarker; + static const char *BandwidthMarker; + static const char *OffsetMarker; + public: CPlayListM3U(void); virtual ~CPlayListM3U(void); virtual bool Load(const std::string& strFileName); virtual void Save(const std::string& strFileName) const; - static CURL GetBestBandwidthStream(const CURL &url, size_t bandwidth); - -protected: - static std::map ParseStreamLine(const std::string &streamLine); }; }