diff --git a/src/buffer/buffer.cpp b/src/buffer/buffer.cpp index d45298a9..233eebce 100644 --- a/src/buffer/buffer.cpp +++ b/src/buffer/buffer.cpp @@ -56,7 +56,6 @@ namespace Buffer { #if DEBUG >= 5 std::cerr << "Thread launched for user " << usr->MyStr << ", socket number " << usr->S.getSocket() << std::endl; #endif - Stream::get()->getReadLock(); usr->myRing = thisStream->getRing(); if (thisStream->getStream()->metadata && thisStream->getHeader().size() > 0){ @@ -67,12 +66,14 @@ namespace Buffer { while (usr->S.connected()){ Util::sleep(5); //sleep 5ms if ( !usr->myRing->playCount || !usr->Send(newSelect)){ - if (usr->myRing->updated){ + // if (usr->myRing->updated){ Stream::get()->getReadLock(); - usr->S.SendNow(Stream::get()->getStream()->metadata.toNetPacked()); + usr->S.SendNow(thisStream->getHeader()); + // std::cerr << "Sending updated header: " << std::endl; + // std::cerr << Stream::get()->getStream()->metadata.toPrettyString() << std::endl; Stream::get()->dropReadLock(); - usr->myRing->updated = false; - } + // usr->myRing->updated = false; + // } if (usr->S.spool()){ while (usr->S.Received().size()){ //delete anything that doesn't end with a newline diff --git a/src/buffer/buffer_stream.cpp b/src/buffer/buffer_stream.cpp index 6335fdfb..0f15e048 100644 --- a/src/buffer/buffer_stream.cpp +++ b/src/buffer/buffer_stream.cpp @@ -63,7 +63,8 @@ namespace Buffer { Storage["totals"]["count"] = tot_count; Storage["totals"]["now"] = now; Storage["buffer"] = name; - Storage["meta"] = Strm->metadata; + ///\todo Fixme +// Storage["meta"] = Strm->metadata; if (Storage["meta"].isMember("audio")){ Storage["meta"]["audio"].removeMember("init"); } diff --git a/src/connectors/conn_http_dynamic.cpp b/src/connectors/conn_http_dynamic.cpp index 24715622..4726731d 100644 --- a/src/connectors/conn_http_dynamic.cpp +++ b/src/connectors/conn_http_dynamic.cpp @@ -2,6 +2,7 @@ /// Contains the main code for the HTTP Dynamic Connector #include +#include #include #include #include @@ -30,7 +31,7 @@ namespace Connector_HTTP { ///\param metadata The current metadata, used to generate the index. ///\param fragnum The index of the current fragment ///\return The generated bootstrap. - std::string dynamicBootstrap(std::string & streamName, JSON::Value & metadata, int fragnum = 0){ + std::string dynamicBootstrap(std::string & streamName, JSON::Value & metadata, bool isLive = false, int fragnum = 0){ std::string empty; MP4::ASRT asrt; @@ -49,17 +50,18 @@ namespace Connector_HTTP { afrt.setTimeScale(1000); //afrt.setQualityEntry(empty, 0); MP4::afrt_runtable afrtrun; - if (metadata.isMember("live")){ + if (isLive){ + fprintf(stderr,"Generating bootstrap for live stream\n"); // restrict data to last 2 fragments, unless an earlier fragment was expressly requested. int count = 0; - unsigned int begin = std::max(0u, metadata["keynum"].size() - 3); - while (begin > 0 && fragnum && metadata["keynum"][begin].asInt() > fragnum){ + unsigned int begin = std::max(0u, metadata["keys"].size() - 3); + while (begin > 0 && fragnum && metadata["keys"][begin]["num"].asInt() > fragnum){ begin--; } - for (int i = begin; i < metadata["keynum"].size(); i++){ - afrtrun.firstFragment = metadata["keynum"][i].asInt(); - afrtrun.firstTimestamp = metadata["keytime"][i].asInt(); - afrtrun.duration = metadata["keylen"][i].asInt(); + for (int i = begin; i < metadata["keys"].size(); i++){ + afrtrun.firstFragment = metadata["keys"][i]["num"].asInt(); + afrtrun.firstTimestamp = metadata["keys"][i]["time"].asInt(); + afrtrun.duration = metadata["keys"][i]["len"].asInt(); afrt.setFragmentRun(afrtrun, count++); } }else{ @@ -95,42 +97,55 @@ namespace Connector_HTTP { ///\param metadata The current metadata, used to generate the index. ///\return The index file for HTTP Dynamic Streaming. std::string dynamicIndex(std::string & streamName, JSON::Value & metadata){ - std::string Result; - if (metadata.isMember("vod")){ - Result = - "\n" - "\n" - "" + streamName + "\n" - "" + metadata["video"]["width"].asString() + "\n" - "" + metadata["video"]["height"].asString() + "\n" - "" + metadata["length"].asString() + ".000\n" - "video/mp4\n" - "recorded\n" - "streaming\n" - "" + Base64::encode(dynamicBootstrap(streamName, metadata)) + "\n" - "\n" - "AgAKb25NZXRhRGF0YQMAAAk=\n" - "\n" - "\n"; - }else{ - Result = - "\n" - "\n" - "" + streamName + "\n" - "" - "video/mp4\n" - "live\n" - "streaming\n" - "\n" - "AgAKb25NZXRhRGF0YQMAAAk=\n" - "\n" - "\n" - "\n"; + std::set videoTracks; + for (JSON::ObjIter it = metadata["tracks"].ObjBegin(); it != metadata["tracks"].ObjEnd(); it++){ + if (it->second["type"] == "video"){ + videoTracks.insert(it->first); + } } -#if DEBUG >= 8 - std::cerr << "Sending this manifest:" << std::endl << Result << std::endl; -#endif - return Result; + + std::stringstream Result; + Result << "" << std::endl; + Result << " " << std::endl; + Result << " " << streamName << "" << std::endl; + Result << " video/mp4" << std::endl; + Result << " streaming" << std::endl; + if (metadata.isMember("vod")){ + ///\todo Update VoD manifest generation. + Result << " " << metadata["video"]["width"].asInt() << "" << std::endl; + Result << " " << metadata["video"]["height"].asInt() << "" << std::endl; + Result << " " << metadata["length"].asInt() << ".000" << std::endl; + Result << " recorded" << std::endl; + Result << " " << Base64::encode(dynamicBootstrap(streamName, metadata, false)) << "" << std::endl; + Result << " " << std::endl; + Result << " AgAKb25NZXRhRGF0YQMAAAk=" << std::endl; + Result << " " << std::endl; + }else{ + Result << " 0.00" << std::endl; + Result << " live" << std::endl; + for (std::set::iterator it = videoTracks.begin(); it != videoTracks.end(); it++){ + Result << " " + "" << std::endl; + } + for (std::set::iterator it = videoTracks.begin(); it != videoTracks.end(); it++){ + Result << " " << std::endl; + Result << " AgAKb25NZXRhRGF0YQMAAAk=" << std::endl; + Result << " " << std::endl; + } + } + Result << "" << std::endl; +//#if DEBUG >= 8 + std::cerr << "Sending this manifest:" << std::endl << Result.str() << std::endl; +//#endif + return Result.str(); } //BuildManifest ///\brief Main function for the HTTP Dynamic Connector @@ -190,10 +205,14 @@ namespace Connector_HTTP { } } } + fprintf(stderr, "%s\n", Strm.metadata.toPrettyString().c_str()); } if (HTTP_R.url.find(".abst") != std::string::npos){ + std::string streamID = HTTP_R.url.substr(HTTP_R.url.find(streamname) + streamname.size() + 1); + streamID = streamID.substr(0, streamID.find(".abst")); + std::cerr << "Requesting bootstrap for stream " << streamID << std::endl; HTTP_S.Clean(); - HTTP_S.SetBody(dynamicBootstrap(streamname, Strm.metadata)); + HTTP_S.SetBody(dynamicBootstrap(streamname, Strm.getTrackById(atoll(streamID.c_str())),Strm.metadata.isMember("live"))); HTTP_S.SetHeader("Content-Type", "binary/octet"); HTTP_S.SetHeader("Cache-Control", "no-cache"); conn.SendNow(HTTP_S.BuildResponse("200", "OK")); @@ -264,7 +283,7 @@ namespace Connector_HTTP { HTTP_S.Clean(); HTTP_S.SetHeader("Content-Type", "video/mp4"); HTTP_S.SetBody(""); - std::string new_strap = dynamicBootstrap(streamname, Strm.metadata, ReqFragment); + std::string new_strap = dynamicBootstrap(streamname, Strm.metadata, Strm.metadata.isMember("live"), ReqFragment); HTTP_S.SetHeader("Content-Length", FlashBufSize + 8 + new_strap.size()); //32+33+btstrp.size()); conn.SendNow(HTTP_S.BuildResponse("200", "OK")); conn.SendNow(new_strap);