Sideloaded SRT file support

This commit is contained in:
Erik Zandvliet 2017-08-23 11:03:56 +02:00 committed by Thulinma
parent dd9e68e4db
commit 0f7f6b3bc7
2 changed files with 155 additions and 11 deletions

View file

@ -85,11 +85,23 @@ namespace Mist {
singleton = this;
isBuffer = false;
hasSrt = false;
srtTrack = 0;
}
void Input::checkHeaderTimes(std::string streamFile) {
struct stat bufStream;
struct stat bufHeader;
struct stat srtStream;
std::string srtFile = streamFile + ".srt";
if (stat(srtFile.c_str(), &srtStream) == 0) {
hasSrt = true;
srtSource.open(srtFile.c_str());
INFO_MSG("File %s opened as srt source", srtFile.c_str());
}
if (stat(streamFile.c_str(), &bufStream) != 0) {
INSANE_MSG("Source is not a file - ignoring header check");
return;
@ -104,8 +116,101 @@ namespace Mist {
INFO_MSG("Overwriting outdated DTSH header file: %s ", headerFile.c_str());
remove(headerFile.c_str());
}
//the same second is not enough - add a 15 second window where we consider it too old
if (hasSrt && bufHeader.st_mtime < srtStream.st_mtime + 15) {
INFO_MSG("Overwriting outdated DTSH header file: %s ", headerFile.c_str());
remove(headerFile.c_str());
}
}
void Input::readSrtHeader() {
if (!hasSrt){return;}
if (!srtSource.good()){return;}
srtTrack = myMeta.tracks.rbegin()->first + 1;
myMeta.tracks[srtTrack].trackID = srtTrack;
myMeta.tracks[srtTrack].type = "subtitle";
myMeta.tracks[srtTrack].codec = "srt";
getNextSrt();
while (srtPack){
myMeta.update(srtPack);
getNextSrt();
}
srtSource.seekg (0, srtSource.beg);
srtSource.clear();
}
void Input::getNextSrt(bool smart){
bool hasPacket = false;
thisPacket.null();
std::string line;
uint32_t index = 0;
uint64_t timestamp = 0;
uint32_t duration = 0;
int lineNr = 0;
std::string data;
while (std::getline(srtSource, line)){// && !line.empty()){
lineNr++;
if(line.empty() || (line.size() == 1 && line.at(0) == '\r') ){
lineNr = 0;
if (duration == 0){
continue;
}
static JSON::Value thisPack;
thisPack.null();
thisPack["trackid"] = srtTrack;
thisPack["bpos"] = (long long)srtSource.tellg();
thisPack["data"] = data;
thisPack["index"] = index;
thisPack["time"] = (long long)timestamp;
thisPack["duration"] = duration;
std::string tmpStr = thisPack.toNetPacked();
srtPack.reInit(tmpStr.data(), tmpStr.size());
return;
}else{
//INFO_MSG("printline size: %d, string: %s", line.size(), line.c_str());
if(lineNr == 1){
index = atoi(line.c_str());
}else if(lineNr == 2){
//timestamp
int from_hour = 0;
int from_min = 0;
int from_sec = 0;
int from_ms = 0;
int to_hour = 0;
int to_min = 0;
int to_sec = 0;
int to_ms = 0;
sscanf (line.c_str(),"%d:%d:%d,%d --> %d:%d:%d,%d",&from_hour, &from_min, &from_sec, &from_ms, &to_hour, &to_min, &to_sec, &to_ms);
timestamp = (from_hour * 60 * 60 *1000) + (from_min * 60 * 1000) + (from_sec * 1000) + from_ms;
duration = ((to_hour * 60 * 60 *1000) + (to_min * 60 * 1000) + (to_sec * 1000) + to_ms) - timestamp;
}else{
//subtitle
if(data.size() > 1){
data.append("\n");
}
data.append(line);
}
}
}
srtPack.null();
FAIL_MSG("Could not get next srt packet!");
}
/// Starts checks the SEM_INPUT lock, starts an angel process and then
int Input::boot(int argc, char * argv[]){
if (!(config->parseArgs(argc, argv))){return 1;}
@ -494,6 +599,9 @@ namespace Mist {
}
void Input::parseHeader() {
if (hasSrt){
readSrtHeader();
}
DEBUG_MSG(DLVL_DONTEVEN, "Parsing the header");
selectedTracks.clear();
std::stringstream trackSpec;
@ -652,28 +760,55 @@ namespace Mist {
std::stringstream trackSpec;
trackSpec << track;
trackSelect(trackSpec.str());
seek(myMeta.tracks[track].keys[keyNum - 1].getTime());
bool isSrt = (hasSrt && track == myMeta.tracks.rbegin()->first);
if (isSrt){
srtTrack = track;
srtSource.seekg (0, srtSource.beg);
srtSource.clear();
}else{
seek(myMeta.tracks[track].keys[keyNum - 1].getTime());
}
long long unsigned int stopTime = myMeta.tracks[track].lastms + 1;
if ((int)myMeta.tracks[track].keys.size() > keyNum - 1 + nProxy.pagesByTrack[track][keyNum].keyNum) {
stopTime = myMeta.tracks[track].keys[keyNum - 1 + nProxy.pagesByTrack[track][keyNum].keyNum].getTime();
}
HIGH_MSG("Playing from %llu to %llu", myMeta.tracks[track].keys[keyNum - 1].getTime(), stopTime);
getNext();
//in case earlier seeking was inprecise, seek to the exact point
while (thisPacket && thisPacket.getTime() < (unsigned long long)myMeta.tracks[track].keys[keyNum - 1].getTime()) {
if (isSrt){
getNextSrt();
//in case earlier seeking was inprecise, seek to the exact point
while (srtPack && srtPack.getTime() < (unsigned long long)myMeta.tracks[track].keys[keyNum - 1].getTime()) {
getNextSrt();
}
}else{
getNext();
//in case earlier seeking was inprecise, seek to the exact point
while (thisPacket && thisPacket.getTime() < (unsigned long long)myMeta.tracks[track].keys[keyNum - 1].getTime()) {
getNext();
}
}
uint64_t lastBuffered = 0;
uint64_t packCounter = 0;
uint64_t byteCounter = 0;
while (thisPacket && thisPacket.getTime() < stopTime) {
if (thisPacket.getTime() >= lastBuffered){
bufferNext(thisPacket);
++packCounter;
byteCounter += thisPacket.getDataLen();
lastBuffered = thisPacket.getTime();
if (isSrt){
while (srtPack && srtPack.getTime() < stopTime) {
if (srtPack.getTime() >= lastBuffered){
bufferNext(srtPack);
++packCounter;
byteCounter += srtPack.getDataLen();
lastBuffered = srtPack.getTime();
}
getNextSrt();
}
}else{
while (thisPacket && thisPacket.getTime() < stopTime) {
if (thisPacket.getTime() >= lastBuffered){
bufferNext(thisPacket);
++packCounter;
byteCounter += thisPacket.getDataLen();
lastBuffered = thisPacket.getTime();
}
getNext();
}
getNext();
}
bufferFinalize(track);
bufferTimer = Util::bootMS() - bufferTimer;

View file

@ -6,6 +6,7 @@
#include <mist/timing.h>
#include <mist/dtsc.h>
#include <mist/shared_memory.h>
#include <fstream>
#include "../io.h"
@ -75,6 +76,14 @@ namespace Mist {
std::map<unsigned int, std::map<unsigned int, unsigned int> > pageCounter;
static Input * singleton;
bool hasSrt;
std::ifstream srtSource;
unsigned int srtTrack;
void readSrtHeader();
void getNextSrt(bool smart = true);
DTSC::Packet srtPack;
};
}