Skip to content
Browse files

bring HLS changes over to rbp branch

  • Loading branch information...
1 parent efef226 commit e30916c184386a380b32e030036468557222015d @micahg committed Aug 26, 2012
View
3 xbmc/cores/dvdplayer/DVDInputStreams/DVDFactoryInputStream.cpp
@@ -63,7 +63,8 @@ CDVDInputStream* CDVDFactoryInputStream::CreateInputStream(IDVDPlayer* pPlayer,
|| file.substr(0, 6) == "tcp://"
|| file.substr(0, 6) == "mms://"
|| file.substr(0, 7) == "mmst://"
- || file.substr(0, 7) == "mmsh://")
+ || file.substr(0, 7) == "mmsh://"
+ || (item.IsInternetStream() && item.IsType(".m3u8")))
return new CDVDInputStreamFFmpeg();
else if(file.substr(0, 8) == "sling://"
|| file.substr(0, 7) == "myth://"
View
13 xbmc/cores/dvdplayer/DVDPlayer.cpp
@@ -72,6 +72,7 @@
#include "storage/MediaManager.h"
#include "dialogs/GUIDialogBusy.h"
#include "dialogs/GUIDialogKaiToast.h"
+#include "xbmc/playlists/PlayListM3U.h"
#include "utils/StringUtils.h"
#include "Util.h"
#include "LangInfo.h"
@@ -542,6 +543,18 @@ bool CDVDPlayer::OpenInputStream()
m_filename = g_mediaManager.TranslateDevicePath("");
}
retry:
+ // before creating the input stream, if this is an HLS playlist then get the
+ // most appropriate bitrate based on our network settings
+ if (filename.Left(7) == "http://" && filename.Right(5) == ".m3u8")
+ {
+ // get the available bandwidth (as per user settings)
+ int maxrate = g_guiSettings.GetInt("network.bandwidth");
+ if(maxrate <= 0)
+ maxrate = INT_MAX;
+
+ // determine the most appropriate stream
+ m_filename = PLAYLIST::CPlayListM3U::GetBestBandwidthStream(m_filename, (size_t)maxrate);
+ }
m_pInputStream = CDVDFactoryInputStream::CreateInputStream(this, m_filename, m_mimetype);
if(m_pInputStream == NULL)
{
View
7 xbmc/playlists/PlayListFactory.cpp
@@ -63,7 +63,8 @@ CPlayList* CPlayListFactory::Create(const CFileItem& item)
|| strMimeType == "text/html")
return new CPlayListPLS();
- if (strMimeType == "audio/x-mpegurl")
+ // online m3u8 files are for hls streaming -- do not treat as playlist
+ if (strMimeType == "audio/x-mpegurl" && !item.IsType(".m3u8"))
return new CPlayListM3U();
if (strMimeType == "application/vnd.ms-wpl")
@@ -118,6 +119,10 @@ bool CPlayListFactory::IsPlaylist(const CFileItem& item)
return true;
*/
+ // online m3u8 files are hls:// -- do not treat as playlist
+ if (item.IsInternetStream() && item.IsType(".m3u8"))
+ return false;
+
if(strMimeType == "audio/x-pn-realaudio"
|| strMimeType == "playlist"
|| strMimeType == "audio/x-mpegurl")
View
117 xbmc/playlists/PlayListM3U.cpp
@@ -21,6 +21,7 @@
#include "PlayListM3U.h"
#include "filesystem/File.h"
+#include "URL.h"
#include "Util.h"
#include "utils/StringUtils.h"
#include "utils/CharsetConverter.h"
@@ -37,6 +38,8 @@ using namespace XFILE;
#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"
// example m3u file:
// #EXTM3U
@@ -48,6 +51,14 @@ using namespace XFILE;
// E:\Program Files\Winamp3\demo.mp3
+// example m3u8 containing streams of different bitrates
+// #EXTM3U
+// #EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=1600000
+// playlist_1600.m3u8
+// #EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=3000000
+// playlist_3000.m3u8
+// #EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=800000
+// playlist_800.m3u8
CPlayListM3U::CPlayListM3U(void)
@@ -170,3 +181,109 @@ void CPlayListM3U::Save(const CStdString& strFileName) const
}
file.Close();
}
+
+CStdString CPlayListM3U::GetBestBandwidthStream(const CStdString &strFileName, 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];
+ CStdString strLine;
+ CStdString strPlaylist = strFileName;
+ size_t maxBandwidth = 0;
+
+ // if we cannot get the last / we wont be able to determine the sub-playlists
+ size_t baseEnd = strPlaylist.rfind('/');
+ if (baseEnd == std::string::npos)
+ return strPlaylist;
+
+ // store the base path (the path without the filename)
+ CStdString basePath = strPlaylist.substr(0, baseEnd + 1);
+
+ // open the file, and if it fails, return
+ CFile file;
+ if (!file.Open(strFileName) )
+ {
+ file.Close();
+ return strPlaylist;
+ }
+
+ // 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;
+ strLine.TrimRight(" \t\r\n");
+ strLine.TrimLeft(" \t");
+
+ // skip the first line
+ if (strLine == M3U_START_MARKER)
+ continue;
+ else if (strLine.Left(strlen(M3U_STREAM_MARKER)) == M3U_STREAM_MARKER)
+ {
+ // parse the line so we can pull out the bandwidth
+ std::map< CStdString, CStdString > params = ParseStreamLine(strLine);
+ std::map< CStdString, CStdString >::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
+ file.ReadString(szLine, 1024);
+ strLine = szLine;
+ strLine.TrimRight(" \t\r\n");
+ strLine.TrimLeft(" \t");
+
+ // 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))
+ strPlaylist = strLine;
+ else
+ strPlaylist = basePath + strLine;
+ }
+ }
+ }
+ }
+
+ CLog::Log(LOGINFO, "Auto-selecting %s based on configured bandwidth.", strPlaylist.c_str());
+
+ return strPlaylist;
+}
+
+std::map< CStdString, CStdString > CPlayListM3U::ParseStreamLine(const CStdString &streamLine)
+{
+ std::map< CStdString, CStdString > params;
+
+ // ensure the line has something beyond the stream marker and ':'
+ if (strlen(streamLine) < strlen(M3U_STREAM_MARKER) + 2)
+ return params;
+
+ // get the actual params following the :
+ CStdString strParams(streamLine.substr(strlen(M3U_STREAM_MARKER) + 1));
+
+ // separate the parameters
+ CStdStringArray vecParams = StringUtils::SplitString(strParams, ",");
+ for (size_t i = 0; i < vecParams.size(); i++)
+ {
+ // split the param, ensure there was an =
+ CStdStringArray vecTuple = StringUtils::SplitString(vecParams[i].Trim(), "=");
+ if (vecTuple.size() < 2)
+ continue;
+
+ // remove white space from name and value and store it in the dictionary
+ params[vecTuple[0].Trim()] = vecTuple[1].Trim();
+ }
+
+ return params;
+}
+
View
8 xbmc/playlists/PlayListM3U.h
@@ -1,6 +1,6 @@
#pragma once
/*
- * Copyright (C) 2005-2008 Team XBMC
+ * Copyright (C) 2005-2012 Team XBMC
* http://www.xbmc.org
*
* This Program is free software; you can redistribute it and/or modify
@@ -31,5 +31,11 @@ class CPlayListM3U :
virtual ~CPlayListM3U(void);
virtual bool Load(const CStdString& strFileName);
virtual void Save(const CStdString& strFileName) const;
+
+ static CStdString GetBestBandwidthStream(const CStdString &strFileName, size_t bandwidth);
+
+protected:
+
+ static std::map< CStdString, CStdString > ParseStreamLine(const CStdString &streamLine);
};
}
View
2 xbmc/settings/Settings.cpp
@@ -101,7 +101,7 @@ void CSettings::Initialize()
m_pictureExtensions = ".png|.jpg|.jpeg|.bmp|.gif|.ico|.tif|.tiff|.tga|.pcx|.cbz|.zip|.cbr|.rar|.m3u|.dng|.nef|.cr2|.crw|.orf|.arw|.erf|.3fr|.dcr|.x3f|.mef|.raf|.mrw|.pef|.sr2|.rss";
m_musicExtensions = ".nsv|.m4a|.flac|.aac|.strm|.pls|.rm|.rma|.mpa|.wav|.wma|.ogg|.mp3|.mp2|.m3u|.mod|.amf|.669|.dmf|.dsm|.far|.gdm|.imf|.it|.m15|.med|.okt|.s3m|.stm|.sfx|.ult|.uni|.xm|.sid|.ac3|.dts|.cue|.aif|.aiff|.wpl|.ape|.mac|.mpc|.mp+|.mpp|.shn|.zip|.rar|.wv|.nsf|.spc|.gym|.adx|.dsp|.adp|.ymf|.ast|.afc|.hps|.xsp|.xwav|.waa|.wvs|.wam|.gcm|.idsp|.mpdsp|.mss|.spt|.rsd|.mid|.kar|.sap|.cmc|.cmr|.dmc|.mpt|.mpd|.rmt|.tmc|.tm8|.tm2|.oga|.url|.pxml|.tta|.rss|.cm3|.cms|.dlt|.brstm|.wtv|.mka";
- m_videoExtensions = ".m4v|.3g2|.3gp|.nsv|.tp|.ts|.ty|.strm|.pls|.rm|.rmvb|.m3u|.ifo|.mov|.qt|.divx|.xvid|.bivx|.vob|.nrg|.img|.iso|.pva|.wmv|.asf|.asx|.ogm|.m2v|.avi|.bin|.dat|.mpg|.mpeg|.mp4|.mkv|.avc|.vp3|.svq3|.nuv|.viv|.dv|.fli|.flv|.rar|.001|.wpl|.zip|.vdr|.dvr-ms|.xsp|.mts|.m2t|.m2ts|.evo|.ogv|.sdp|.avs|.rec|.url|.pxml|.vc1|.h264|.rcv|.rss|.mpls|.webm|.bdmv|.wtv";
+ m_videoExtensions = ".m4v|.3g2|.3gp|.nsv|.tp|.ts|.ty|.strm|.pls|.rm|.rmvb|.m3u|.m3u8|.ifo|.mov|.qt|.divx|.xvid|.bivx|.vob|.nrg|.img|.iso|.pva|.wmv|.asf|.asx|.ogm|.m2v|.avi|.bin|.dat|.mpg|.mpeg|.mp4|.mkv|.avc|.vp3|.svq3|.nuv|.viv|.dv|.fli|.flv|.rar|.001|.wpl|.zip|.vdr|.dvr-ms|.xsp|.mts|.m2t|.m2ts|.evo|.ogv|.sdp|.avs|.rec|.url|.pxml|.vc1|.h264|.rcv|.rss|.mpls|.webm|.bdmv|.wtv";
m_discStubExtensions = ".disc";
// internal music extensions
m_musicExtensions += "|.sidstream|.oggstream|.nsfstream|.asapstream|.cdda";

0 comments on commit e30916c

Please sign in to comment.
Something went wrong with that request. Please try again.