diff --git a/src/connectors/conn_http.cpp b/src/connectors/conn_http.cpp
index 829ec1b0..134b75ae 100644
--- a/src/connectors/conn_http.cpp
+++ b/src/connectors/conn_http.cpp
@@ -309,6 +309,54 @@ namespace Connector_HTTP {
return ret;
}
+ // send smil MBR index
+ if (url.length() > 6 && url.substr(url.length() - 5, 5) == ".smil"){
+ std::string streamname = url.substr(1, url.length() - 6);
+ Util::Stream::sanitizeName(streamname);
+ JSON::Value ServConf = JSON::fromFile(Util::getTmpFolder() + "streamlist");
+
+ std::string host = H.GetHeader("Host");
+ if (host.find(':')){
+ host.resize(host.find(':'));
+ }
+
+ std::string port, url_rel;
+
+ for (JSON::ArrIter it = ServConf["config"]["protocols"].ArrBegin(); it != ServConf["config"]["protocols"].ArrEnd(); it++){
+ const std::string & cName = ( *it)["connector"].asStringRef();
+ if (cName != "RTMP"){continue;}
+ //if we have the RTMP port,
+ if (capabilities.isMember(cName) && capabilities[cName].isMember("optional") && capabilities[cName]["optional"].isMember("port")){
+ //get the default port if none is set
+ if (( *it)["port"].asInt() == 0){
+ port = capabilities[cName]["optional"]["port"]["default"].asString();
+ }
+ //extract url
+ if (capabilities[cName].isMember("url_rel")){
+ url_rel = capabilities[cName]["url_rel"].asString();
+ if (url_rel.find('$')){
+ url_rel.resize(url_rel.find('$'));
+ }
+ }
+ }
+ }
+
+ std::string trackSources;//this string contains all track sources for MBR smil
+ for (JSON::ObjIter it = ServConf["streams"][streamname]["meta"]["tracks"].ObjBegin(); it != ServConf["streams"][streamname]["meta"]["tracks"].ObjEnd(); it++){//for all tracks
+ if (it->second.isMember("type") && it->second["type"].asString() == "video"){
+ trackSources += " \n";
+ }
+ }
+
+ H.Clean();
+ H.SetHeader("Content-Type", "application/smil");
+ H.SetHeader("Server", "mistserver/" PACKAGE_VERSION "/" + Util::Config::libver);
+ H.SetBody("\n \n \n \n \n \n"+trackSources+" \n \n");
+ long long int ret = Util::getMS();
+ conn.SendNow(H.BuildResponse("200", "OK"));
+ return ret;
+ }
+
if ((url.length() > 9 && url.substr(0, 6) == "/info_" && url.substr(url.length() - 3, 3) == ".js")
|| (url.length() > 10 && url.substr(0, 7) == "/embed_" && url.substr(url.length() - 3, 3) == ".js")){
std::string streamname;
@@ -549,6 +597,9 @@ namespace Connector_HTTP {
if (url.length() > 6 && url.substr(url.length() - 5, 5) == ".html"){
return "internal";
}
+ if (url.length() > 6 && url.substr(url.length() - 5, 5) == ".smil"){
+ return "internal";
+ }
}
if (url == "/crossdomain.xml"){
return "internal";
diff --git a/src/output/output_rtmp.cpp b/src/output/output_rtmp.cpp
index 10815cfa..e0e01bee 100644
--- a/src/output/output_rtmp.cpp
+++ b/src/output/output_rtmp.cpp
@@ -38,6 +38,61 @@ namespace Mist {
OutRTMP::~OutRTMP() {}
+ void OutRTMP::parseVars(std::string data){
+ std::string varname;
+ std::string varval;
+ bool trackSwitch = false;
+ // position where a part start (e.g. after &)
+ size_t pos = 0;
+ while (pos < data.length()){
+ size_t nextpos = data.find('&', pos);
+ if (nextpos == std::string::npos){
+ nextpos = data.length();
+ }
+ size_t eq_pos = data.find('=', pos);
+ if (eq_pos < nextpos){
+ // there is a key and value
+ varname = data.substr(pos, eq_pos - pos);
+ varval = data.substr(eq_pos + 1, nextpos - eq_pos - 1);
+ }else{
+ // no value, only a key
+ varname = data.substr(pos, nextpos - pos);
+ varval.clear();
+ }
+ //SetVar(urlunescape(varname), urlunescape(varval));
+
+ if (varname == "track"){
+ long long int selTrack = JSON::Value(varval).asInt();
+ if (myMeta){
+ if (myMeta.tracks.count(selTrack)){
+ std::string & delThis = myMeta.tracks[selTrack].type;
+ for (std::set::iterator it = selectedTracks.begin(); it != selectedTracks.end(); it++){
+ if (myMeta.tracks[*it].type == delThis){
+ selectedTracks.erase(it);
+ trackSwitch = true;
+ break;
+ }
+ }
+ selectedTracks.insert(selTrack);
+ }
+ }else{
+ selectedTracks.insert(selTrack);
+ }
+ }
+
+ if (nextpos == std::string::npos){
+ // in case the string is gigantic
+ break;
+ }
+ // erase &
+ pos = nextpos + 1;
+ }
+ if (trackSwitch){
+ seek(currentPacket.getTime());
+ }
+ }
+
+
void OutRTMP::init(Util::Config * cfg) {
Output::init(cfg);
capa["name"] = "RTMP";
@@ -446,6 +501,14 @@ namespace Mist {
int playMessageType = messageType;
int playStreamId = streamId;
streamName = amfData.getContentP(3)->StrValue();
+
+ //handle variables
+ if (streamName.find('?') != std::string::npos){
+ std::string tmpVars = streamName.substr(streamName.find('?') + 1);
+ Util::Stream::sanitizeName(streamName);
+ parseVars(tmpVars);
+ }
+
initialize();
//send a status reply
diff --git a/src/output/output_rtmp.h b/src/output/output_rtmp.h
index b262753d..35a6831b 100644
--- a/src/output/output_rtmp.h
+++ b/src/output/output_rtmp.h
@@ -14,6 +14,7 @@ namespace Mist {
void sendNext();
void sendHeader();
protected:
+ void parseVars(std::string data);
std::string app_name;
bool sending;
int counter;