Various fixes to generic segmenter code
Segmenter: when using the external writer, do not re-open a playlist to adjust the target duration Segmenter: edit comments and fix logic for opening the playlist with streams which are live and vod at the same time Segmenter: fix init of playlist data when using an external writer
This commit is contained in:
parent
e641793195
commit
211d9eac30
2 changed files with 69 additions and 21 deletions
24
lib/url.cpp
24
lib/url.cpp
|
@ -87,7 +87,9 @@ HTTP::URL::URL(const std::string &url){
|
|||
path.erase(prevslash + 1, path.length());
|
||||
}
|
||||
}
|
||||
path = Encodings::URL::decode(path);
|
||||
if (!isLocalPath()){
|
||||
path = Encodings::URL::decode(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
// user, pass, host and port are now definitely between proto_sep and first_slash
|
||||
|
@ -196,6 +198,8 @@ std::string HTTP::URL::getUrl() const{
|
|||
ret += "/";
|
||||
if (protocol == "rtsp"){
|
||||
if (path.size()){ret += Encodings::URL::encode(path, "/:=@[]#?&");}
|
||||
}else if (isLocalPath()){
|
||||
if (path.size()){ret += Encodings::URL::encode(path, "/:=@[]+ ");}
|
||||
}else{
|
||||
if (path.size()){ret += Encodings::URL::encode(path, "/:=@[]");}
|
||||
}
|
||||
|
@ -238,6 +242,8 @@ std::string HTTP::URL::getProxyUrl() const{
|
|||
ret += "/";
|
||||
if (protocol == "rtsp"){
|
||||
if (path.size()){ret += Encodings::URL::encode(path, "/:=@[]#?&");}
|
||||
}else if (isLocalPath()){
|
||||
if (path.size()){ret += Encodings::URL::encode(path, "/:=@[]+ ");}
|
||||
}else{
|
||||
if (path.size()){ret += Encodings::URL::encode(path, "/:=@[]");}
|
||||
}
|
||||
|
@ -265,6 +271,8 @@ std::string HTTP::URL::getBareUrl() const{
|
|||
ret += "/";
|
||||
if (protocol == "rtsp"){
|
||||
if (path.size()){ret += Encodings::URL::encode(path, "/:=@[]#?&");}
|
||||
}else if (isLocalPath()){
|
||||
if (path.size()){ret += Encodings::URL::encode(path, "/:=@[]+ ");}
|
||||
}else{
|
||||
if (path.size()){ret += Encodings::URL::encode(path, "/:=@[]");}
|
||||
}
|
||||
|
@ -273,7 +281,12 @@ std::string HTTP::URL::getBareUrl() const{
|
|||
|
||||
/// Returns a string guaranteed to end in a slash, pointing to the base directory-equivalent of the URL
|
||||
std::string HTTP::URL::getBase() const{
|
||||
std::string tmpUrl = getBareUrl();
|
||||
std::string tmpUrl;
|
||||
if (isLocalPath()){
|
||||
tmpUrl = getFilePath();
|
||||
}else{
|
||||
tmpUrl = getBareUrl();
|
||||
}
|
||||
size_t slashPos = tmpUrl.rfind('/');
|
||||
if (slashPos == std::string::npos){
|
||||
tmpUrl += "/";
|
||||
|
@ -287,7 +300,12 @@ std::string HTTP::URL::getBase() const{
|
|||
/// If the given URL is in a parent directory of the URL, it will be relative
|
||||
/// Otherwise, it will be absolute
|
||||
std::string HTTP::URL::getLinkFrom(const HTTP::URL & fromUrl) const{
|
||||
std::string to = getUrl();
|
||||
std::string to;
|
||||
if (isLocalPath()){
|
||||
to = getFilePath();
|
||||
}else{
|
||||
to = getUrl();
|
||||
}
|
||||
std::string from = fromUrl.getBase();
|
||||
if (to.substr(0, from.size()) == from){
|
||||
return to.substr(from.size());
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <mist/util.h>
|
||||
#include <mist/urireader.h>
|
||||
#include <sys/file.h>
|
||||
#include <mist/encode.h>
|
||||
|
||||
/*LTS-START*/
|
||||
#include <arpa/inet.h>
|
||||
|
@ -1360,12 +1361,33 @@ namespace Mist{
|
|||
if (origTargetPtr){
|
||||
origTarget = origTargetPtr;
|
||||
if (origTarget.rfind('?') != std::string::npos){
|
||||
std::map<std::string, std::string> tmpParams;
|
||||
HTTP::parseVars(origTarget.substr(origTarget.rfind('?') + 1), tmpParams);
|
||||
origTarget.erase(origTarget.rfind('?'));
|
||||
if (tmpParams.count("m3u8")){
|
||||
targetParams["m3u8"] = tmpParams["m3u8"];
|
||||
}
|
||||
if (tmpParams.count("segment")){
|
||||
targetParams["segment"] = tmpParams["segment"];
|
||||
}
|
||||
}
|
||||
}else if (config->hasOption("target")){
|
||||
origTarget = config->getString("target");
|
||||
}
|
||||
Util::streamVariables(origTarget, streamName);
|
||||
// Check if the target segment contains any of the required variables
|
||||
if (targetParams.count("m3u8")){
|
||||
std::string tmpTarget;
|
||||
if (targetParams.count("segment")){
|
||||
tmpTarget = targetParams["segment"];
|
||||
}else{
|
||||
tmpTarget = origTarget;
|
||||
}
|
||||
if (tmpTarget.find("$currentMediaTime") == std::string::npos && tmpTarget.find("$segmentCounter") == std::string::npos){
|
||||
FAIL_MSG("Target segmented output does not contain a currentMediaTime or segmentCounter: %s", tmpTarget.c_str());
|
||||
Util::logExitReason("Target segmented output does not contain a currentMediaTime or segmentCounter: %s", tmpTarget.c_str());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (targetParams.count("maxEntries")){
|
||||
maxEntries = atoll(targetParams["maxEntries"].c_str());
|
||||
}
|
||||
|
@ -1380,7 +1402,9 @@ namespace Mist{
|
|||
if (!systemBoot){systemBoot = (Util::unixMS() - Util::bootMS());}
|
||||
// Create a new or connect to an existing playlist file
|
||||
if (!plsConn){
|
||||
playlistLocation = HTTP::URL(origTarget).link(targetParams["m3u8"]);
|
||||
std::string plsRel = targetParams["m3u8"];
|
||||
Util::streamVariables(plsRel, streamName);
|
||||
playlistLocation = HTTP::URL(config->getString("target")).link(plsRel);
|
||||
if (playlistLocation.isLocalPath()){
|
||||
playlistLocationString = playlistLocation.getFilePath();
|
||||
INFO_MSG("Segmenting to local playlist '%s'", playlistLocationString.c_str());
|
||||
|
@ -1455,9 +1479,11 @@ namespace Mist{
|
|||
INFO_MSG("Appending to existing remote playlist file '%s'", playlistLocationString.c_str());
|
||||
}else{
|
||||
WARN_MSG("Overwriting existing remote playlist file '%s'", playlistLocationString.c_str());
|
||||
reInitPlaylist = true;
|
||||
}
|
||||
}else{
|
||||
INFO_MSG("Creating new remote playlist file '%s'", playlistLocationString.c_str());
|
||||
reInitPlaylist = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1510,7 +1536,9 @@ namespace Mist{
|
|||
std::string newTarget = origTarget;
|
||||
Util::replace(newTarget, "$currentMediaTime", JSON::Value(currentStartTime).asString());
|
||||
Util::replace(newTarget, "$segmentCounter", JSON::Value(segmentCount).asString());
|
||||
Util::streamVariables(newTarget, streamName);
|
||||
currentTarget = newTarget;
|
||||
config->getOption("target", true).append(currentTarget);
|
||||
if (newTarget == "-"){
|
||||
INFO_MSG("Outputting %s to stdout with %s format", streamName.c_str(),
|
||||
capa["name"].asString().c_str());
|
||||
|
@ -1649,7 +1677,7 @@ namespace Mist{
|
|||
if (!M.getLive()){
|
||||
uint64_t unixMs = M.getBootMsOffset() + systemBoot + currentStartTime;
|
||||
reinitPlaylist(playlistBuffer, targetAge, maxEntries, segmentCount, segmentsRemoved, unixMs, targetDuration, playlistLocation);
|
||||
}else if (!maxEntries && !targetAge){
|
||||
}else if (!maxEntries && !targetAge && playlistLocation.isLocalPath()){
|
||||
// If we are appending to an existing playlist, we need to recover the playlistBuffer and reopen the playlist
|
||||
HTTP::URIReader inFile(playlistLocationString);
|
||||
char *newBuffer;
|
||||
|
@ -1661,7 +1689,7 @@ namespace Mist{
|
|||
reinitPlaylist(playlistBuffer, targetAge, maxEntries, segmentCount, segmentsRemoved, unixMs, targetDuration, playlistLocation);
|
||||
connectToFile(playlistLocationString, false, &plsConn);
|
||||
}
|
||||
// Else we are in a sliding window playlist, so it will already get overwritten
|
||||
// Else we are in a sliding window playlist, so it will automatically get overwritten
|
||||
}
|
||||
// Remove older entries in the playlist
|
||||
if (maxEntries || targetAge){
|
||||
|
@ -1682,20 +1710,22 @@ namespace Mist{
|
|||
}
|
||||
|
||||
// Keep track of filenames written, so that they can be added to the playlist file
|
||||
std::string newTarget = origTarget;
|
||||
std::string newTarget;
|
||||
if (targetParams.count("segment")){
|
||||
HTTP::URL targetUrl = HTTP::URL(config->getString("target")).link(targetParams["segment"]);
|
||||
if (targetUrl.isLocalPath()){
|
||||
newTarget = targetUrl.getFilePath();
|
||||
}else{
|
||||
newTarget = targetUrl.getUrl();
|
||||
}
|
||||
}else{
|
||||
newTarget = origTarget;
|
||||
}
|
||||
currentStartTime = lastPacketTime;
|
||||
segmentCount++;
|
||||
// Replace variable currentMediaTime and segmentCounter
|
||||
if (targetParams.count("m3u8")){
|
||||
if (newTarget.find("$currentMediaTime") == std::string::npos && newTarget.find("$segmentCounter") == std::string::npos){
|
||||
FAIL_MSG("Target segmented output does not contain a currentMediaTime or segmentCounter: %s", newTarget.c_str());
|
||||
Util::logExitReason("Target segmented output does not contain a currentMediaTime or segmentCounter: %s", newTarget.c_str());
|
||||
onFinish();
|
||||
break;
|
||||
}
|
||||
Util::replace(newTarget, "$currentMediaTime", JSON::Value(currentStartTime).asString());
|
||||
Util::replace(newTarget, "$segmentCounter", JSON::Value(segmentCount).asString());
|
||||
}
|
||||
Util::replace(newTarget, "$currentMediaTime", JSON::Value(currentStartTime).asString());
|
||||
Util::replace(newTarget, "$segmentCounter", JSON::Value(segmentCount).asString());
|
||||
Util::streamVariables(newTarget, streamName);
|
||||
if (newTarget.rfind('?') != std::string::npos){
|
||||
newTarget.erase(newTarget.rfind('?'));
|
||||
}
|
||||
|
@ -1752,8 +1782,8 @@ namespace Mist{
|
|||
onFinish();
|
||||
// Write last segment
|
||||
if (targetParams.count("m3u8")){
|
||||
// If this is VOD, we can finally open up the connection to the playlist file
|
||||
if (M.getVod()){connectToFile(playlistLocationString, false, &plsConn);}
|
||||
// If this is a non-live source, we can finally open up the connection to the playlist file
|
||||
if (!M.getLive()){connectToFile(playlistLocationString, false, &plsConn);}
|
||||
if (plsConn){
|
||||
std::string segment = HTTP::URL(currentTarget).getLinkFrom(playlistLocation);
|
||||
if (M.getLive()){
|
||||
|
|
Loading…
Add table
Reference in a new issue