Various improvements and simplifications to HLS
This commit is contained in:
parent
224e3a3f0d
commit
54d927c9df
1 changed files with 46 additions and 66 deletions
|
@ -5,12 +5,10 @@
|
|||
namespace Mist {
|
||||
bool OutHLS::isReadyForPlay() {
|
||||
if (myMeta.tracks.size()){
|
||||
for (std::map<unsigned int, DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++){
|
||||
if (it->second.fragments.size() >= 3){
|
||||
if (myMeta.mainTrack().fragments.size() > 4){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -57,9 +55,12 @@ namespace Mist {
|
|||
updateMeta();
|
||||
std::stringstream result;
|
||||
//parse single track
|
||||
result << "#EXTM3U\r\n#EXT-X-TARGETDURATION:" << (myMeta.tracks[tid].biggestFragment() / 1000) + 1 << "\r\n";
|
||||
uint32_t target_dur = (myMeta.tracks[tid].biggestFragment() / 1000) + 1;
|
||||
result << "#EXTM3U\r\n#EXT-X-VERSION:3\r\n#EXT-X-TARGETDURATION:" << target_dur << "\r\n";
|
||||
|
||||
std::deque<std::string> lines;
|
||||
std::deque<uint16_t> durs;
|
||||
uint32_t total_dur = 0;
|
||||
for (std::deque<DTSC::Fragment>::iterator it = myMeta.tracks[tid].fragments.begin(); it != myMeta.tracks[tid].fragments.end(); it++) {
|
||||
long long int starttime = myMeta.tracks[tid].getKey(it->getNumber()).getTime();
|
||||
long long duration = it->getDuration();
|
||||
|
@ -68,16 +69,27 @@ namespace Mist {
|
|||
}
|
||||
char lineBuf[400];
|
||||
if (sessId.size()){
|
||||
snprintf(lineBuf, 400, "#EXTINF:%lld, no desc\r\n%lld_%lld.ts?sessId=%s\r\n", ((duration + 500) / 1000), starttime, starttime + duration, sessId.c_str());
|
||||
snprintf(lineBuf, 400, "#EXTINF:%f,\r\n%lld_%lld.ts?sessId=%s\r\n", (double)duration/1000, starttime, starttime + duration, sessId.c_str());
|
||||
}else{
|
||||
snprintf(lineBuf, 400, "#EXTINF:%lld, no desc\r\n%lld_%lld.ts\r\n", ((duration + 500) / 1000), starttime, starttime + duration);
|
||||
snprintf(lineBuf, 400, "#EXTINF:%f,\r\n%lld_%lld.ts\r\n", (double)duration/1000, starttime, starttime + duration);
|
||||
}
|
||||
durs.push_back(duration);
|
||||
total_dur += duration;
|
||||
lines.push_back(lineBuf);
|
||||
}
|
||||
unsigned int skippedLines = 0;
|
||||
if (myMeta.live && lines.size()) {
|
||||
//only print the last segment when VoD
|
||||
lines.pop_back();
|
||||
total_dur -= durs.back();
|
||||
durs.pop_back();
|
||||
//skip the first two segments when live, unless that brings us under 4 target durations
|
||||
while ((total_dur-durs.front()) > (target_dur * 4000) && skippedLines < 2) {
|
||||
lines.pop_front();
|
||||
total_dur -= durs.front();
|
||||
durs.pop_front();
|
||||
++skippedLines;
|
||||
}
|
||||
}
|
||||
|
||||
result << "#EXT-X-MEDIA-SEQUENCE:" << myMeta.tracks[tid].missedFrags + skippedLines << "\r\n";
|
||||
|
@ -86,7 +98,7 @@ namespace Mist {
|
|||
result << lines.front();
|
||||
lines.pop_front();
|
||||
}
|
||||
if ( !myMeta.live){
|
||||
if (!myMeta.live || total_dur == 0) {
|
||||
result << "#EXT-X-ENDLIST\r\n";
|
||||
}
|
||||
DEBUG_MSG(DLVL_HIGH, "Sending this index: %s", result.str().c_str());
|
||||
|
@ -114,24 +126,6 @@ namespace Mist {
|
|||
capa["methods"][0u]["priority"] = 9ll;
|
||||
}
|
||||
|
||||
int OutHLS::canSeekms(unsigned int ms){
|
||||
//no tracks? Frame too new by definition.
|
||||
if ( !myMeta.tracks.size()){
|
||||
return 1;
|
||||
}
|
||||
//check main track
|
||||
DTSC::Track & mainTrack = myMeta.tracks[*selectedTracks.begin()];
|
||||
//return "too late" if one track is past this point
|
||||
if (ms < mainTrack.firstms){
|
||||
return -1;
|
||||
}
|
||||
//return "too early" if one track is not yet at this point
|
||||
if (ms > mainTrack.lastms){
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void OutHLS::onHTTP() {
|
||||
std::string method = H.method;
|
||||
std::string sessId = H.GetVar("sessId");
|
||||
|
@ -207,37 +201,22 @@ namespace Mist {
|
|||
}
|
||||
}
|
||||
|
||||
//Keep a reference to the main track
|
||||
//This is called vidTrack, even for audio-only streams
|
||||
DTSC::Track & Trk = myMeta.tracks[vidTrack];
|
||||
|
||||
if (myMeta.live) {
|
||||
unsigned int timeout = 0;
|
||||
int seekable;
|
||||
do {
|
||||
seekable = canSeekms(from);
|
||||
/// \todo Detection of out-of-range parts.
|
||||
if (seekable > 0){
|
||||
//time out after 21 seconds
|
||||
if (++timeout > 42){
|
||||
myConn.close();
|
||||
break;
|
||||
}
|
||||
Util::wait(500);
|
||||
updateMeta();
|
||||
}
|
||||
}while (myConn && seekable > 0);
|
||||
if (seekable < 0){
|
||||
if (from < Trk.firstms){
|
||||
H.Clean();
|
||||
H.setCORSHeaders();
|
||||
H.SetBody("The requested fragment is no longer kept in memory on the server and cannot be served.\n");
|
||||
myConn.SendNow(H.BuildResponse("412", "Fragment out of range"));
|
||||
myConn.SendNow(H.BuildResponse("404", "Fragment out of range"));
|
||||
H.Clean(); //clean for any possible next requests
|
||||
DEBUG_MSG(DLVL_WARN, "Fragment @ %llu too old", from);
|
||||
WARN_MSG("Fragment @ %llu too old", from);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
seek(from);
|
||||
ts_from = from;
|
||||
lastVid = from * 90;
|
||||
|
||||
H.Clean();
|
||||
H.SetHeader("Content-Type", "video/mp2t");
|
||||
H.setCORSHeaders();
|
||||
|
@ -246,22 +225,18 @@ namespace Mist {
|
|||
H.Clean();
|
||||
return;
|
||||
}
|
||||
H.StartResponse(H, myConn, VLCworkaround);
|
||||
|
||||
unsigned int fragCounter = myMeta.tracks[vidTrack].missedFrags;
|
||||
for (std::deque<DTSC::Fragment>::iterator it = myMeta.tracks[vidTrack].fragments.begin(); it != myMeta.tracks[vidTrack].fragments.end(); it++){
|
||||
long long int starttime = myMeta.tracks[vidTrack].getKey(it->getNumber()).getTime();
|
||||
if (starttime <= from && starttime + it->getDuration() > from){
|
||||
EXTREME_MSG("setting continuity counter for PAT/PMT to %d",fragCounter);
|
||||
contCounters[0]=fragCounter; //PAT continuity counter
|
||||
contCounters[4096]=fragCounter; //PMT continuity counter
|
||||
break;
|
||||
}
|
||||
++fragCounter;
|
||||
}
|
||||
H.StartResponse(H, myConn, VLCworkaround);
|
||||
//we assume whole fragments - but timestamps may be altered at will
|
||||
uint32_t fragIndice = Trk.timeToFragnum(from);
|
||||
contCounters[0] = Trk.missedFrags + fragIndice; //PAT continuity counter
|
||||
contCounters[4096] = Trk.missedFrags + fragIndice; //PMT continuity counter
|
||||
packCounter = 0;
|
||||
parseData = true;
|
||||
wantRequest = false;
|
||||
seek(from);
|
||||
ts_from = from;
|
||||
lastVid = from * 90;
|
||||
} else {
|
||||
initialize();
|
||||
std::string request = H.url.substr(H.url.find("/", 5) + 1);
|
||||
|
@ -273,6 +248,11 @@ namespace Mist {
|
|||
}
|
||||
H.SetHeader("Cache-Control", "no-cache");
|
||||
H.setCORSHeaders();
|
||||
if (!myMeta.tracks.size()){
|
||||
H.SendResponse("404", "Not online or found", myConn);
|
||||
H.Clean();
|
||||
return;
|
||||
}
|
||||
if(method == "OPTIONS" || method == "HEAD"){
|
||||
H.SendResponse("200", "OK", myConn);
|
||||
H.Clean();
|
||||
|
|
Loading…
Add table
Reference in a new issue