smil support by Oswald de Bruin
This commit is contained in:
parent
f09e58e034
commit
f538bd0d93
3 changed files with 115 additions and 0 deletions
|
@ -309,6 +309,54 @@ namespace Connector_HTTP {
|
||||||
return ret;
|
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 += " <video src='"+ streamname + "?track=" + it->second["trackid"].asString() + "' height='" + it->second["height"].asString() + "' system-bitrate='" + it->second["bps"].asString() + "' width='" + it->second["width"].asString() + "' />\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
H.Clean();
|
||||||
|
H.SetHeader("Content-Type", "application/smil");
|
||||||
|
H.SetHeader("Server", "mistserver/" PACKAGE_VERSION "/" + Util::Config::libver);
|
||||||
|
H.SetBody("<smil>\n <head>\n <meta base='rtmp://" + host + ":" + port + url_rel + "' />\n </head>\n <body>\n <switch>\n"+trackSources+" </switch>\n </body>\n</smil>");
|
||||||
|
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")
|
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")){
|
|| (url.length() > 10 && url.substr(0, 7) == "/embed_" && url.substr(url.length() - 3, 3) == ".js")){
|
||||||
std::string streamname;
|
std::string streamname;
|
||||||
|
@ -549,6 +597,9 @@ namespace Connector_HTTP {
|
||||||
if (url.length() > 6 && url.substr(url.length() - 5, 5) == ".html"){
|
if (url.length() > 6 && url.substr(url.length() - 5, 5) == ".html"){
|
||||||
return "internal";
|
return "internal";
|
||||||
}
|
}
|
||||||
|
if (url.length() > 6 && url.substr(url.length() - 5, 5) == ".smil"){
|
||||||
|
return "internal";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (url == "/crossdomain.xml"){
|
if (url == "/crossdomain.xml"){
|
||||||
return "internal";
|
return "internal";
|
||||||
|
|
|
@ -38,6 +38,61 @@ namespace Mist {
|
||||||
|
|
||||||
OutRTMP::~OutRTMP() {}
|
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<unsigned long>::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) {
|
void OutRTMP::init(Util::Config * cfg) {
|
||||||
Output::init(cfg);
|
Output::init(cfg);
|
||||||
capa["name"] = "RTMP";
|
capa["name"] = "RTMP";
|
||||||
|
@ -446,6 +501,14 @@ namespace Mist {
|
||||||
int playMessageType = messageType;
|
int playMessageType = messageType;
|
||||||
int playStreamId = streamId;
|
int playStreamId = streamId;
|
||||||
streamName = amfData.getContentP(3)->StrValue();
|
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();
|
initialize();
|
||||||
|
|
||||||
//send a status reply
|
//send a status reply
|
||||||
|
|
|
@ -14,6 +14,7 @@ namespace Mist {
|
||||||
void sendNext();
|
void sendNext();
|
||||||
void sendHeader();
|
void sendHeader();
|
||||||
protected:
|
protected:
|
||||||
|
void parseVars(std::string data);
|
||||||
std::string app_name;
|
std::string app_name;
|
||||||
bool sending;
|
bool sending;
|
||||||
int counter;
|
int counter;
|
||||||
|
|
Loading…
Add table
Reference in a new issue