Sideloaded SRT file support
This commit is contained in:
parent
dd9e68e4db
commit
0f7f6b3bc7
2 changed files with 155 additions and 11 deletions
|
@ -85,11 +85,23 @@ namespace Mist {
|
||||||
|
|
||||||
singleton = this;
|
singleton = this;
|
||||||
isBuffer = false;
|
isBuffer = false;
|
||||||
|
|
||||||
|
hasSrt = false;
|
||||||
|
srtTrack = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Input::checkHeaderTimes(std::string streamFile) {
|
void Input::checkHeaderTimes(std::string streamFile) {
|
||||||
struct stat bufStream;
|
struct stat bufStream;
|
||||||
struct stat bufHeader;
|
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) {
|
if (stat(streamFile.c_str(), &bufStream) != 0) {
|
||||||
INSANE_MSG("Source is not a file - ignoring header check");
|
INSANE_MSG("Source is not a file - ignoring header check");
|
||||||
return;
|
return;
|
||||||
|
@ -104,8 +116,101 @@ namespace Mist {
|
||||||
INFO_MSG("Overwriting outdated DTSH header file: %s ", headerFile.c_str());
|
INFO_MSG("Overwriting outdated DTSH header file: %s ", headerFile.c_str());
|
||||||
remove(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
|
/// Starts checks the SEM_INPUT lock, starts an angel process and then
|
||||||
int Input::boot(int argc, char * argv[]){
|
int Input::boot(int argc, char * argv[]){
|
||||||
if (!(config->parseArgs(argc, argv))){return 1;}
|
if (!(config->parseArgs(argc, argv))){return 1;}
|
||||||
|
@ -494,6 +599,9 @@ namespace Mist {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Input::parseHeader() {
|
void Input::parseHeader() {
|
||||||
|
if (hasSrt){
|
||||||
|
readSrtHeader();
|
||||||
|
}
|
||||||
DEBUG_MSG(DLVL_DONTEVEN, "Parsing the header");
|
DEBUG_MSG(DLVL_DONTEVEN, "Parsing the header");
|
||||||
selectedTracks.clear();
|
selectedTracks.clear();
|
||||||
std::stringstream trackSpec;
|
std::stringstream trackSpec;
|
||||||
|
@ -652,28 +760,55 @@ namespace Mist {
|
||||||
std::stringstream trackSpec;
|
std::stringstream trackSpec;
|
||||||
trackSpec << track;
|
trackSpec << track;
|
||||||
trackSelect(trackSpec.str());
|
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;
|
long long unsigned int stopTime = myMeta.tracks[track].lastms + 1;
|
||||||
if ((int)myMeta.tracks[track].keys.size() > keyNum - 1 + nProxy.pagesByTrack[track][keyNum].keyNum) {
|
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();
|
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);
|
HIGH_MSG("Playing from %llu to %llu", myMeta.tracks[track].keys[keyNum - 1].getTime(), stopTime);
|
||||||
getNext();
|
if (isSrt){
|
||||||
//in case earlier seeking was inprecise, seek to the exact point
|
getNextSrt();
|
||||||
while (thisPacket && thisPacket.getTime() < (unsigned long long)myMeta.tracks[track].keys[keyNum - 1].getTime()) {
|
//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();
|
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 lastBuffered = 0;
|
||||||
uint64_t packCounter = 0;
|
uint64_t packCounter = 0;
|
||||||
uint64_t byteCounter = 0;
|
uint64_t byteCounter = 0;
|
||||||
while (thisPacket && thisPacket.getTime() < stopTime) {
|
if (isSrt){
|
||||||
if (thisPacket.getTime() >= lastBuffered){
|
while (srtPack && srtPack.getTime() < stopTime) {
|
||||||
bufferNext(thisPacket);
|
if (srtPack.getTime() >= lastBuffered){
|
||||||
++packCounter;
|
bufferNext(srtPack);
|
||||||
byteCounter += thisPacket.getDataLen();
|
++packCounter;
|
||||||
lastBuffered = thisPacket.getTime();
|
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);
|
bufferFinalize(track);
|
||||||
bufferTimer = Util::bootMS() - bufferTimer;
|
bufferTimer = Util::bootMS() - bufferTimer;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <mist/timing.h>
|
#include <mist/timing.h>
|
||||||
#include <mist/dtsc.h>
|
#include <mist/dtsc.h>
|
||||||
#include <mist/shared_memory.h>
|
#include <mist/shared_memory.h>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
#include "../io.h"
|
#include "../io.h"
|
||||||
|
|
||||||
|
@ -75,6 +76,14 @@ namespace Mist {
|
||||||
std::map<unsigned int, std::map<unsigned int, unsigned int> > pageCounter;
|
std::map<unsigned int, std::map<unsigned int, unsigned int> > pageCounter;
|
||||||
|
|
||||||
static Input * singleton;
|
static Input * singleton;
|
||||||
|
|
||||||
|
bool hasSrt;
|
||||||
|
std::ifstream srtSource;
|
||||||
|
unsigned int srtTrack;
|
||||||
|
|
||||||
|
void readSrtHeader();
|
||||||
|
void getNextSrt(bool smart = true);
|
||||||
|
DTSC::Packet srtPack;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue