Added machine readable exit reasons, INPUT_END trigger, OUTPUT_END trigger, and updated RECORDING_END trigger to include all of these.
This commit is contained in:
parent
a16d98b7b2
commit
b0d4422d27
47 changed files with 493 additions and 256 deletions
|
@ -93,6 +93,7 @@ namespace Mist{
|
|||
Input::Input(Util::Config *cfg) : InOutBase(){
|
||||
config = cfg;
|
||||
standAlone = true;
|
||||
Util::Config::binaryType = Util::INPUT;
|
||||
|
||||
JSON::Value option;
|
||||
option["long"] = "json";
|
||||
|
@ -399,8 +400,8 @@ namespace Mist{
|
|||
}
|
||||
|
||||
if (!checkArguments()){
|
||||
FAIL_MSG("Setup failed - exiting");
|
||||
return 0;
|
||||
Util::logExitReason(ER_UNKNOWN, "Setup failed - exiting");
|
||||
return exitAndLogReason();
|
||||
}
|
||||
|
||||
IPC::semaphore playerLock;
|
||||
|
@ -476,8 +477,12 @@ namespace Mist{
|
|||
streamStatus.master = false;
|
||||
if (streamStatus){streamStatus.mapped[0] = STRMSTAT_INIT;}
|
||||
}
|
||||
int ret = 0;
|
||||
if (preRun()){ret = run();}
|
||||
int ret = 1;
|
||||
if (preRun()){
|
||||
ret = run();
|
||||
}else{
|
||||
return exitAndLogReason();
|
||||
}
|
||||
if (playerLock){
|
||||
playerLock.unlink();
|
||||
char pageName[NAME_BUFFER_SIZE];
|
||||
|
@ -514,7 +519,9 @@ namespace Mist{
|
|||
// Abandon all semaphores, ye who enter here.
|
||||
playerLock.abandon();
|
||||
pullLock.abandon();
|
||||
if (!preRun()){return 0;}
|
||||
if (!preRun()){
|
||||
return exitAndLogReason();
|
||||
}
|
||||
return run();
|
||||
}
|
||||
Util::Procs::fork_complete();
|
||||
|
@ -538,8 +545,9 @@ namespace Mist{
|
|||
}
|
||||
HIGH_MSG("Done waiting for child for stream %s", streamName.c_str());
|
||||
// if the exit was clean, don't restart it
|
||||
if (WIFEXITED(status) && (WEXITSTATUS(status) == 0)){
|
||||
INFO_MSG("Input for stream %s shut down cleanly", streamName.c_str());
|
||||
int exitCode = WEXITSTATUS(status);
|
||||
if (WIFEXITED(status) && (exitCode == 0 || exitCode == 1)){
|
||||
HIGH_MSG("Input for stream %s shut down cleanly", streamName.c_str());
|
||||
break;
|
||||
}
|
||||
if (playerLock){
|
||||
|
@ -548,12 +556,49 @@ namespace Mist{
|
|||
streamStatus.init(pageName, 2, false, false);
|
||||
if (streamStatus){streamStatus.mapped[0] = STRMSTAT_INVALID;}
|
||||
}
|
||||
#if DEBUG >= DLVL_DEVEL
|
||||
// Fire the INPUT_ABORT trigger if the child process ends with an abnormal exit code
|
||||
// Prevents automatic restarts of the input for unrecoverable errors
|
||||
if (WIFEXITED(status)){
|
||||
char exitReason[256];
|
||||
memcpy(exitReason, Util::exitReason, 256);
|
||||
if (exitCode == 2){
|
||||
WARN_MSG("Child process %u exited with exit code %i (major error occurred), cleaning up...", pid, exitCode);
|
||||
Util::logExitReason(ER_UNKNOWN, "Child process %u exited with exit code %i (major error occurred)", pid, exitCode);
|
||||
}else if (exitCode == 132){
|
||||
WARN_MSG("Child process %u exited with exit code %i (SIGILL), cleaning up...", pid, exitCode);
|
||||
Util::logExitReason(ER_SIGILL, "Child process %u exited with exit code %i (SIGILL)", pid, exitCode);
|
||||
}else if (exitCode == 133){
|
||||
WARN_MSG("Child process %u exited with exit code %i (SIGTRAP)", pid, exitCode);
|
||||
Util::logExitReason(ER_SIGTRAP, "Child process %u exited with exit code %i (SIGTRAP)", pid, exitCode);
|
||||
}else if (exitCode == 134){
|
||||
WARN_MSG("Child process %u exited with exit code %i (SIGABRT)", pid, exitCode);
|
||||
Util::logExitReason(ER_SIGABRT, "Child process %u exited with exit code %i (SIGABRT)", pid, exitCode);
|
||||
}else if (exitCode == 136){
|
||||
WARN_MSG("Child process %u exited with exit code %i (SIGFPE)", pid, exitCode);
|
||||
Util::logExitReason(ER_SIGFPE, "Child process %u exited with exit code %i (SIGFPE)", pid, exitCode);
|
||||
}else if (exitCode == 137){
|
||||
WARN_MSG("Child process %u exited with exit code %i (used too much memory), cleaning up...", pid, exitCode);
|
||||
Util::logExitReason(ER_MEMORY, "Child process %u exited with exit code %i (used too much memory)", pid, exitCode);
|
||||
}else if (exitCode == 138){
|
||||
WARN_MSG("Child process %u exited with exit code %i (SIGBUS)", pid, exitCode);
|
||||
Util::logExitReason(ER_SIGBUS, "Child process %u exited with exit code %i (SIGBUS)", pid, exitCode);
|
||||
}else if (exitCode == 139){
|
||||
WARN_MSG("Child process %u exited with exit code %i (SEGFAULT)", pid, exitCode);
|
||||
Util::logExitReason(ER_SEGFAULT, "Child process %u exited with exit code %i (SEGFAULT)", pid, exitCode);
|
||||
}else{
|
||||
WARN_MSG("Child process %u exited with an unhandled exit code %i, cleaning up...", pid, exitCode);
|
||||
Util::logExitReason(ER_UNKNOWN, "Child process %u exited with an unhandled exit code %i", pid, exitCode);
|
||||
}
|
||||
doInputAbortTrigger(pid, Util::mRExitReason, Util::exitReason);
|
||||
memcpy(Util::exitReason, exitReason, 256);
|
||||
}
|
||||
|
||||
#if DEBUG >= DLVL_DEVEL
|
||||
WARN_MSG(
|
||||
"Input for stream %s uncleanly shut down! Aborting restart; this is a development build.",
|
||||
streamName.c_str());
|
||||
break;
|
||||
#else
|
||||
#else
|
||||
if (config->is_active){
|
||||
WARN_MSG("Input for stream %s uncleanly shut down! Cleaning and restarting...", streamName.c_str());
|
||||
}else{
|
||||
|
@ -609,8 +654,8 @@ namespace Mist{
|
|||
if (needHeader()){
|
||||
uint64_t timer = Util::getMicros();
|
||||
if (!readHeader() || (!M && needsLock())){
|
||||
FAIL_MSG("Reading header for '%s' failed.", config->getString("input").c_str());
|
||||
return 0;
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Reading header for '%s' failed", config->getString("input").c_str());
|
||||
return exitAndLogReason();
|
||||
}
|
||||
timer = Util::getMicros(timer);
|
||||
INFO_MSG("Created header in %.3f ms (%zu tracks)", (double)timer/1000.0, M?M.trackCount():(size_t)0);
|
||||
|
@ -639,7 +684,7 @@ namespace Mist{
|
|||
INFO_MSG("Starting serve");
|
||||
serve();
|
||||
}
|
||||
return 0;
|
||||
return exitAndLogReason();
|
||||
}
|
||||
|
||||
void Input::convert(){
|
||||
|
@ -694,6 +739,40 @@ namespace Mist{
|
|||
outMeta.toFile(fileName + ".dtsh");
|
||||
}
|
||||
|
||||
// Fires the `INPUT_ABORT` trigger. Allows overrides to allow parent processes
|
||||
// to fire the trigger for child processes which have already exited (EG segfaults)
|
||||
void Input::doInputAbortTrigger(pid_t pid, char *mRExitReason, char *exitReason){
|
||||
// Calculate variables required for the trigger
|
||||
if (Util::Config::binaryType == Util::INPUT && Triggers::shouldTrigger("INPUT_ABORT", streamName)){
|
||||
std::ostringstream pidString;
|
||||
pidString << pid;
|
||||
std::string payload = streamName + "\n" + config->getString("input") + "\n" \
|
||||
+ "MistIn" + capa["name"].asString() + "\n" + pidString.str() + "\n" \
|
||||
+ mRExitReason + "\n" + exitReason;
|
||||
Triggers::doTrigger("INPUT_ABORT", payload, streamName);
|
||||
}
|
||||
}
|
||||
|
||||
// Logs the current exit reason and returns a 0 or 1 depending on whether
|
||||
// this was a clean exit or not
|
||||
bool Input::exitAndLogReason(){
|
||||
int returnCode = 1;
|
||||
// If no reason is set at all, return the default status
|
||||
if (!Util::exitReason[0]){
|
||||
INFO_MSG("Input closing without a set exit reason");
|
||||
}else if(strncmp(Util::mRExitReason, "CLEAN", 5) == 0){
|
||||
INFO_MSG("Input closing cleanly with reason: %s", Util::exitReason);
|
||||
returnCode = 0;
|
||||
}else{
|
||||
WARN_MSG("Input closing unclean, reason: %s", Util::exitReason);
|
||||
}
|
||||
// If this is an unclean exit, fire the INPUT_ABORT trigger
|
||||
if (returnCode){
|
||||
doInputAbortTrigger(getpid(), Util::mRExitReason, Util::exitReason);
|
||||
}
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
/// Checks in the server configuration if this stream is set to always on or not.
|
||||
/// Returns true if it is, or if the stream could not be found in the configuration.
|
||||
/// If the compiled default debug level is < INFO, instead returns false if the stream is not found.
|
||||
|
@ -748,7 +827,7 @@ namespace Mist{
|
|||
if (Triggers::shouldTrigger("STREAM_READY", config->getString("streamname"))){
|
||||
std::string payload = config->getString("streamname") + "\n" + capa["name"].asStringRef();
|
||||
if (!Triggers::doTrigger("STREAM_READY", payload, config->getString("streamname"))){
|
||||
Util::logExitReason("STREAM_READY trigger returned false");
|
||||
Util::logExitReason(ER_TRIGGER, "STREAM_READY trigger returned false");
|
||||
config->is_active = false;
|
||||
}
|
||||
}
|
||||
|
@ -789,7 +868,6 @@ namespace Mist{
|
|||
config->is_active = false;
|
||||
}
|
||||
finish();
|
||||
INFO_MSG("Input closing clean, reason: %s", Util::exitReason);
|
||||
userSelect.clear();
|
||||
if (!isThread()){
|
||||
if (streamStatus){streamStatus.mapped[0] = STRMSTAT_OFF;}
|
||||
|
@ -837,7 +915,7 @@ namespace Mist{
|
|||
}
|
||||
/*LTS-END*/
|
||||
if (!ret && ((Util::bootSecs() - activityCounter) >= INPUT_TIMEOUT)){
|
||||
Util::logExitReason("no activity for %u seconds", Util::bootSecs() - activityCounter);
|
||||
Util::logExitReason(ER_CLEAN_INACTIVE, "no activity for %u seconds", Util::bootSecs() - activityCounter);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -882,14 +960,13 @@ namespace Mist{
|
|||
if (config->getBool("realtime")){
|
||||
realtimeMainLoop();
|
||||
finish();
|
||||
INFO_MSG("Real-time input closing clean; reason: %s", Util::exitReason);
|
||||
return;
|
||||
}
|
||||
|
||||
meta.reInit(streamName, false);
|
||||
|
||||
if (!openStreamSource()){
|
||||
FAIL_MSG("Unable to connect to source");
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Unable to connect to source");
|
||||
return;
|
||||
}
|
||||
parseStreamHeader();
|
||||
|
@ -897,9 +974,9 @@ namespace Mist{
|
|||
if (publishesTracks()){
|
||||
std::set<size_t> validTracks = M.getMySourceTracks(getpid());
|
||||
if (!validTracks.size()){
|
||||
Util::logExitReason(ER_CLEAN_EOF, "No tracks found, cancelling pull");
|
||||
userSelect.clear();
|
||||
finish();
|
||||
INFO_MSG("No tracks found, cancelling");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -908,7 +985,6 @@ namespace Mist{
|
|||
closeStreamSource();
|
||||
userSelect.clear();
|
||||
finish();
|
||||
INFO_MSG("Input closing clean; reason: %s", Util::exitReason);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -929,17 +1005,17 @@ namespace Mist{
|
|||
}
|
||||
while (thisPacket && config->is_active && userSelect[thisIdx]){
|
||||
if (userSelect[thisIdx].getStatus() & COMM_STATUS_REQDISCONNECT){
|
||||
Util::logExitReason("buffer requested shutdown");
|
||||
Util::logExitReason(ER_CLEAN_LIVE_BUFFER_REQ, "buffer requested shutdown");
|
||||
break;
|
||||
}
|
||||
if (isSingular() && !bufferActive()){
|
||||
Util::logExitReason("Buffer shut down");
|
||||
Util::logExitReason(ER_SHM_LOST, "Buffer shut down");
|
||||
return;
|
||||
}
|
||||
bufferLivePacket(thisPacket);
|
||||
getNext();
|
||||
if (!thisPacket){
|
||||
Util::logExitReason("no more data");
|
||||
Util::logExitReason(ER_CLEAN_EOF, "no more data");
|
||||
break;
|
||||
}
|
||||
if (thisPacket && !userSelect.count(thisIdx)){
|
||||
|
@ -952,7 +1028,7 @@ namespace Mist{
|
|||
if (statComm){
|
||||
if (!statComm){
|
||||
config->is_active = false;
|
||||
Util::logExitReason("received shutdown request from controller");
|
||||
Util::logExitReason(ER_CLEAN_CONTROLLER_REQ, "received shutdown request from controller");
|
||||
return;
|
||||
}
|
||||
uint64_t now = Util::bootSecs();
|
||||
|
@ -1080,7 +1156,7 @@ namespace Mist{
|
|||
while (config->is_active){
|
||||
getNext();
|
||||
if (!thisPacket){
|
||||
Util::logExitReason("no more data");
|
||||
Util::logExitReason(ER_CLEAN_EOF, "no more data");
|
||||
break;
|
||||
}
|
||||
idx = realTimeTrackMap.count(thisIdx) ? realTimeTrackMap[thisIdx] : INVALID_TRACK_ID;
|
||||
|
@ -1088,7 +1164,7 @@ namespace Mist{
|
|||
userSelect[idx].reload(streamName, idx, COMM_STATUS_ACTIVE | COMM_STATUS_SOURCE | COMM_STATUS_DONOTTRACK);
|
||||
}
|
||||
if (userSelect[idx].getStatus() & COMM_STATUS_REQDISCONNECT){
|
||||
Util::logExitReason("buffer requested shutdown");
|
||||
Util::logExitReason(ER_CLEAN_LIVE_BUFFER_REQ, "buffer requested shutdown");
|
||||
break;
|
||||
}
|
||||
while (config->is_active && userSelect[idx] &&
|
||||
|
@ -1114,7 +1190,7 @@ namespace Mist{
|
|||
if (statComm){
|
||||
if (statComm.getStatus() & COMM_STATUS_REQDISCONNECT){
|
||||
config->is_active = false;
|
||||
Util::logExitReason("received shutdown request from controller");
|
||||
Util::logExitReason(ER_CLEAN_CONTROLLER_REQ, "received shutdown request from controller");
|
||||
return;
|
||||
}
|
||||
uint64_t now = Util::bootSecs();
|
||||
|
|
|
@ -95,6 +95,8 @@ namespace Mist{
|
|||
virtual void connStats(Comms::Connections & statComm);
|
||||
virtual void parseHeader();
|
||||
bool bufferFrame(size_t track, uint32_t keyNum);
|
||||
void doInputAbortTrigger(pid_t pid, char *mRExitReason, char *exitReason);
|
||||
bool exitAndLogReason();
|
||||
|
||||
uint64_t activityCounter;
|
||||
|
||||
|
|
|
@ -80,12 +80,12 @@ namespace Mist{
|
|||
bool inputAAC::checkArguments(){
|
||||
if (!config->getString("streamname").size()){
|
||||
if (config->getString("output") == "-"){
|
||||
std::cerr << "Output to stdout not yet supported" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Output to stdout not yet supported");
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
if (config->getString("output") != "-"){
|
||||
std::cerr << "File output in player mode not supported" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "File output in player mode not supported");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -94,7 +94,10 @@ namespace Mist{
|
|||
|
||||
bool inputAAC::preRun(){
|
||||
inFile.open(config->getString("input"));
|
||||
if (!inFile || inFile.isEOF()){return false;}
|
||||
if (!inFile || inFile.isEOF()){
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Reading header for '%s' failed: Could not open input stream", config->getString("input").c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
struct stat statData;
|
||||
lastModTime = 0;
|
||||
|
@ -131,7 +134,7 @@ namespace Mist{
|
|||
size_t bytesRead = 0;
|
||||
|
||||
if (!inFile || inFile.isEOF()){
|
||||
INFO_MSG("Could not open input stream");
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Reading header for '%s' failed: Could not open input stream", config->getString("input").c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -140,15 +143,12 @@ namespace Mist{
|
|||
// Read fixed + variable header
|
||||
inFile.readSome(aacData, bytesRead, 6);
|
||||
if (bytesRead < 6){
|
||||
WARN_MSG("Not enough bytes left in buffer. Quitting...");
|
||||
// Dump for debug purposes
|
||||
INFO_MSG("Header contains bytes: %x %x %x %x %x %x", aacData[0]
|
||||
, aacData[1], aacData[2], aacData[3], aacData[4], aacData[5]);
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Reading header for '%s' failed: Not enough bytes left in buffer", config->getString("input").c_str());
|
||||
return false;
|
||||
}
|
||||
// Confirm syncword (= FFF)
|
||||
if (aacData[0] != 0xFF || (aacData[1] & 0xF0) != 0xF0){
|
||||
WARN_MSG("Invalid sync word at start of header");
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Reading header for '%s' failed: Invalid sync word at start of header", config->getString("input").c_str());
|
||||
return false;
|
||||
}
|
||||
// Calculate the starting position of the next frame
|
||||
|
@ -172,7 +172,7 @@ namespace Mist{
|
|||
// Create ADTS object of complete frame info
|
||||
aac::adts adtsPack(aacFrame, frameSize);
|
||||
if (!adtsPack){
|
||||
WARN_MSG("Could not parse ADTS package!");
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Reading header for '%s' failed: Could not parse ADTS package", config->getString("input").c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -231,7 +231,7 @@ namespace Mist{
|
|||
size_t disregardAmount = 0;
|
||||
|
||||
if (!inFile || inFile.isEOF()){
|
||||
INFO_MSG("Reached EOF");
|
||||
Util::logExitReason(ER_CLEAN_EOF, "Reached EOF");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -251,9 +251,10 @@ namespace Mist{
|
|||
aacData[3] == 0x54 && aacData[4] == 0x41 && aacData[5] == 0x47){
|
||||
inFile.readAll(aacData, bytesRead);
|
||||
INFO_MSG("Throwing out %zu bytes of metadata...", bytesRead);
|
||||
Util::logExitReason(ER_CLEAN_EOF, "Reached EOF");
|
||||
return;
|
||||
}
|
||||
WARN_MSG("Invalid sync word at start of header");
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Invalid sync word at start of header");
|
||||
return;
|
||||
}
|
||||
// Calculate the starting position of the next frame
|
||||
|
@ -278,21 +279,7 @@ namespace Mist{
|
|||
// Create ADTS object of frame
|
||||
aac::adts adtsPack(aacFrame, frameSize);
|
||||
if (!adtsPack){
|
||||
WARN_MSG("Could not parse ADTS package!");
|
||||
WARN_MSG("Current frame info:");
|
||||
WARN_MSG("Current frame pos: %zu", filePos);
|
||||
WARN_MSG("Next frame pos: %zu", nextFramePos);
|
||||
WARN_MSG("Frame size expected: %" PRIu64, frameSize);
|
||||
WARN_MSG("Bytes read: %zu", bytesRead);
|
||||
WARN_MSG("ADTS getAACProfile: %li", adtsPack.getAACProfile());
|
||||
WARN_MSG("ADTS getFrequencyIndex: %li", adtsPack.getFrequencyIndex());
|
||||
WARN_MSG("ADTS getFrequency: %li", adtsPack.getFrequency());
|
||||
WARN_MSG("ADTS getChannelConfig: %li", adtsPack.getChannelConfig());
|
||||
WARN_MSG("ADTS getChannelCount: %li", adtsPack.getChannelCount());
|
||||
WARN_MSG("ADTS getHeaderSize: %li", adtsPack.getHeaderSize());
|
||||
WARN_MSG("ADTS getPayloadSize: %li", adtsPack.getPayloadSize());
|
||||
WARN_MSG("ADTS getCompleteSize: %li", adtsPack.getCompleteSize());
|
||||
WARN_MSG("ADTS getSampleCount: %li", adtsPack.getSampleCount());
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Could not parse ADTS package");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -313,8 +300,7 @@ namespace Mist{
|
|||
if (trks.size()){
|
||||
audioTrack = *(trks.begin());
|
||||
}else{
|
||||
Util::logExitReason("no audio track in header");
|
||||
FAIL_MSG("No audio track in header - aborting");
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "No audio track in header");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,17 +43,17 @@ namespace Mist{
|
|||
|
||||
bool inputAV::checkArguments(){
|
||||
if (config->getString("input") == "-"){
|
||||
std::cerr << "Input from stdin not yet supported" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Input from stdin not yet supported");
|
||||
return false;
|
||||
}
|
||||
if (!config->getString("streamname").size()){
|
||||
if (config->getString("output") == "-"){
|
||||
std::cerr << "Output to stdout not yet supported" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Output to stdout not yet supported");
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
if (config->getString("output") != "-"){
|
||||
std::cerr << "File output in player mode not supported" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "File output in player mode not supported");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ namespace Mist{
|
|||
if (ret != 0){
|
||||
char errstr[300];
|
||||
av_strerror(ret, errstr, 300);
|
||||
FAIL_MSG("Could not open file: %s", errstr);
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Could not open file: %s", errstr);
|
||||
return false; // Couldn't open file
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,7 @@ namespace Mist{
|
|||
if (ret < 0){
|
||||
char errstr[300];
|
||||
av_strerror(ret, errstr, 300);
|
||||
FAIL_MSG("Could not find stream info: %s", errstr);
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Could not find stream info: %s", errstr);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -195,7 +195,7 @@ namespace Mist{
|
|||
thisPacket.null();
|
||||
preRun();
|
||||
// failure :-(
|
||||
FAIL_MSG("getNext failed");
|
||||
Util::logExitReason(ER_UNKNOWN, "getNext failed");
|
||||
}
|
||||
|
||||
void inputAV::seek(uint64_t seekTime, size_t idx){
|
||||
|
|
|
@ -489,7 +489,7 @@ namespace Mist{
|
|||
}
|
||||
if (hasPush){everHadPush = true;}
|
||||
if (!hasPush && everHadPush && !resumeMode && config->is_active){
|
||||
Util::logExitReason("source disconnected for non-resumable stream");
|
||||
Util::logExitReason(ER_CLEAN_EOF, "source disconnected for non-resumable stream");
|
||||
if (streamStatus){streamStatus.mapped[0] = STRMSTAT_SHUTDOWN;}
|
||||
config->is_active = false;
|
||||
userSelect.clear();
|
||||
|
|
|
@ -210,12 +210,12 @@ namespace Mist{
|
|||
if (!needsLock()){return true;}
|
||||
if (!config->getString("streamname").size()){
|
||||
if (config->getString("output") == "-"){
|
||||
std::cerr << "Output to stdout not yet supported" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Output to stdout not yet supported");
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
if (config->getString("output") != "-"){
|
||||
std::cerr << "File output in player mode not supported" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "File output in player mode not supported");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -223,7 +223,7 @@ namespace Mist{
|
|||
// open File
|
||||
F = fopen(config->getString("input").c_str(), "r+b");
|
||||
if (!F){
|
||||
HIGH_MSG("Could not open file %s", config->getString("input").c_str());
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Could not open file %s", config->getString("input").c_str());
|
||||
return false;
|
||||
}
|
||||
fseek(F, 0, SEEK_SET);
|
||||
|
@ -236,17 +236,20 @@ namespace Mist{
|
|||
}
|
||||
|
||||
bool inputDTSC::readHeader(){
|
||||
if (!F){return false;}
|
||||
if (!F){
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Reading header for '%s' failed: Could not open input stream", config->getString("input").c_str());
|
||||
return false;
|
||||
}
|
||||
size_t moreHeader = 0;
|
||||
do{
|
||||
char hdr[8];
|
||||
fseek(F, moreHeader, SEEK_SET);
|
||||
if (fread(hdr, 8, 1, F) != 1){
|
||||
FAIL_MSG("Could not read header @ bpos %zu", moreHeader);
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Reading header for '%s' failed: Could not read header @ bpos %zu", config->getString("input").c_str(), moreHeader);
|
||||
return false;
|
||||
}
|
||||
if (memcmp(hdr, DTSC::Magic_Header, 4)){
|
||||
FAIL_MSG("File does not have a DTSC header @ bpos %zu", moreHeader);
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Reading header for '%s' failed: File does not have a DTSC header @ bpos %zu", config->getString("input").c_str(), moreHeader);
|
||||
return false;
|
||||
}
|
||||
size_t pktLen = Bit::btohl(hdr + 4);
|
||||
|
@ -283,6 +286,7 @@ namespace Mist{
|
|||
fseek(F, thisPos.bytePos, SEEK_SET);
|
||||
if (feof(F)){
|
||||
thisPacket.null();
|
||||
Util::logExitReason(ER_CLEAN_EOF, "End of file reached");
|
||||
return;
|
||||
}
|
||||
clearerr(F);
|
||||
|
@ -290,9 +294,9 @@ namespace Mist{
|
|||
lastreadpos = ftell(F);
|
||||
if (fread(buffer, 4, 1, F) != 1){
|
||||
if (feof(F)){
|
||||
INFO_MSG("End of file reached while seeking @ %" PRIu64, lastreadpos);
|
||||
Util::logExitReason(ER_CLEAN_EOF, "End of file reached while seeking @ %" PRIu64, lastreadpos);
|
||||
}else{
|
||||
ERROR_MSG("Could not seek to next @ %" PRIu64, lastreadpos);
|
||||
Util::logExitReason(ER_UNKNOWN, "Could not seek to next @ %" PRIu64, lastreadpos);
|
||||
}
|
||||
thisPacket.null();
|
||||
return;
|
||||
|
@ -306,13 +310,13 @@ namespace Mist{
|
|||
if (memcmp(buffer, DTSC::Magic_Packet, 4) == 0){version = 1;}
|
||||
if (memcmp(buffer, DTSC::Magic_Packet2, 4) == 0){version = 2;}
|
||||
if (version == 0){
|
||||
ERROR_MSG("Invalid packet header @ %#" PRIx64 " - %.4s != %.4s @ %" PRIu64, lastreadpos,
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Invalid packet header @ %#" PRIx64 " - %.4s != %.4s @ %" PRIu64, lastreadpos,
|
||||
buffer, DTSC::Magic_Packet2, lastreadpos);
|
||||
thisPacket.null();
|
||||
return;
|
||||
}
|
||||
if (fread(buffer + 4, 4, 1, F) != 1){
|
||||
ERROR_MSG("Could not read packet size @ %" PRIu64, lastreadpos);
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Could not read packet size @ %" PRIu64, lastreadpos);
|
||||
thisPacket.null();
|
||||
return;
|
||||
}
|
||||
|
@ -321,7 +325,7 @@ namespace Mist{
|
|||
pBuf.resize(8 + packSize);
|
||||
memcpy((char *)pBuf.data(), buffer, 8);
|
||||
if (fread((void *)(pBuf.data() + 8), packSize, 1, F) != 1){
|
||||
ERROR_MSG("Could not read packet @ %" PRIu64, lastreadpos);
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Could not read packet @ %" PRIu64, lastreadpos);
|
||||
thisPacket.null();
|
||||
return;
|
||||
}
|
||||
|
@ -353,7 +357,7 @@ namespace Mist{
|
|||
}
|
||||
if (cmd == "error"){
|
||||
thisPacket.getString("msg", cmd);
|
||||
Util::logExitReason("%s", cmd.c_str());
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "%s", cmd.c_str());
|
||||
thisPacket.null();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ namespace Mist{
|
|||
key = Encodings::Base64::decode(config->getString("key"));
|
||||
if (key == ""){
|
||||
if (config->getString("keyseed") == "" || config->getString("keyid") == ""){
|
||||
std::cerr << "No key given, and no keyseed/keyid geven" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "No key given, and no keyseed/keyid given");
|
||||
return false;
|
||||
}
|
||||
std::string tmpSeed = Encodings::Base64::decode(config->getString("keyseed"));
|
||||
|
@ -66,29 +66,35 @@ namespace Mist{
|
|||
}
|
||||
|
||||
if (config->getString("input") == "-"){
|
||||
std::cerr << "Input from stdin not yet supported" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Input from stdin not yet supported");
|
||||
return false;
|
||||
}
|
||||
if (!config->getString("streamname").size()){
|
||||
if (config->getString("output") == "-"){
|
||||
std::cerr << "Output to stdout not yet supported" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Output to stdout not yet supported");
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
if (config->getString("output") != "-"){
|
||||
std::cerr << "File output in player mode not supported" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "File output in player mode not supported");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// open File
|
||||
inFile = DTSC::File(config->getString("input"));
|
||||
if (!inFile){return false;}
|
||||
if (!inFile){
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Opening input '%s' failed", config->getString("input").c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool inputDTSC::readHeader(){
|
||||
if (!inFile){return false;}
|
||||
if (!inFile){
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Reading header for '%s' failed: Could not open input stream", config->getString("input").c_str());
|
||||
return false;
|
||||
}
|
||||
DTSC::File tmp(config->getString("input") + ".dtsh");
|
||||
if (tmp){
|
||||
myMeta = tmp.getMeta();
|
||||
|
@ -96,7 +102,7 @@ namespace Mist{
|
|||
return true;
|
||||
}
|
||||
if (inFile.getMeta().moreheader < 0 || inFile.getMeta().tracks.size() == 0){
|
||||
DEBUG_MSG(DLVL_FAIL, "Missing external header file");
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Missing external header file");
|
||||
return false;
|
||||
}
|
||||
myMeta = DTSC::Meta(inFile.getMeta());
|
||||
|
|
|
@ -105,12 +105,12 @@ namespace Mist{
|
|||
bool InputEBML::checkArguments(){
|
||||
if (!config->getString("streamname").size()){
|
||||
if (config->getString("output") == "-"){
|
||||
std::cerr << "Output to stdout not yet supported" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Output to stdout not yet supported");
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
if (config->getString("output") != "-"){
|
||||
std::cerr << "File output in player mode not supported" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "File output in player mode not supported");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -150,7 +150,10 @@ namespace Mist{
|
|||
|
||||
int fin = -1, fout = -1;
|
||||
Util::Procs::StartPiped(args, &fin, &fout, 0);
|
||||
if (fout == -1){return false;}
|
||||
if (fout == -1){
|
||||
Util::logExitReason(ER_PROCESS_SPECIFIC, "Unable to start mkv-exec process `%s`", args);
|
||||
return false;
|
||||
}
|
||||
dup2(fout, 0);
|
||||
inFile.open(0);
|
||||
return true;
|
||||
|
@ -161,7 +164,10 @@ namespace Mist{
|
|||
}else{
|
||||
// open File
|
||||
inFile.open(config->getString("input"));
|
||||
if (!inFile){return false;}
|
||||
if (!inFile){
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Opening input '%s' failed", config->getString("input").c_str());
|
||||
return false;
|
||||
}
|
||||
standAlone = inFile.isSeekable();
|
||||
}
|
||||
return true;
|
||||
|
@ -261,7 +267,10 @@ namespace Mist{
|
|||
}
|
||||
|
||||
bool InputEBML::readHeader(){
|
||||
if (!inFile){return false;}
|
||||
if (!inFile){
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Reading header for '%s' failed: Could not open input stream", config->getString("input").c_str());
|
||||
return false;
|
||||
}
|
||||
if (!meta || (needsLock() && isSingular())){
|
||||
meta.reInit(isSingular() ? streamName : "");
|
||||
}
|
||||
|
@ -728,7 +737,7 @@ namespace Mist{
|
|||
}
|
||||
}
|
||||
if (seekPos > readPos + readBuffer.size()){
|
||||
Util::logExitReason("Input file seek abort");
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Input file seek abort");
|
||||
config->is_active = false;
|
||||
readBufferOffset = 0;
|
||||
return;
|
||||
|
|
|
@ -40,17 +40,17 @@ namespace Mist{
|
|||
|
||||
bool inputFLAC::checkArguments(){
|
||||
if (config->getString("input") == "-"){
|
||||
std::cerr << "Input from stdin not yet supported" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Input from stdin not yet supported");
|
||||
return false;
|
||||
}
|
||||
if (!config->getString("streamname").size()){
|
||||
if (config->getString("output") == "-"){
|
||||
std::cerr << "Output to stdout not yet supported" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Output to stdout not yet supported");
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
if (config->getString("output") != "-"){
|
||||
std::cerr << "File output in player mode not supported" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "File output in player mode not supported");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,10 @@ namespace Mist{
|
|||
|
||||
bool inputFLAC::preRun(){
|
||||
inFile = fopen(config->getString("input").c_str(), "r");
|
||||
if (!inFile){return false;}
|
||||
if (!inFile){
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Opening input '%s' failed", config->getString("input").c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -81,7 +84,7 @@ namespace Mist{
|
|||
bool inputFLAC::readMagicPacket(){
|
||||
char magic[4];
|
||||
if (fread(magic, 4, 1, inFile) != 1){
|
||||
FAIL_MSG("Could not read magic word - aborting!");
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Could not read magic word - aborting!");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -90,12 +93,15 @@ namespace Mist{
|
|||
return true;
|
||||
}
|
||||
|
||||
FAIL_MSG("Not a FLAC file - aborting!");
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Not a FLAC file - aborting!");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool inputFLAC::readHeader(){
|
||||
if (!inFile){return false;}
|
||||
if (!inFile){
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Opening input '%s' failed", config->getString("input").c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (readExistingHeader()){
|
||||
WARN_MSG("header exists, read old one");
|
||||
|
@ -118,7 +124,7 @@ namespace Mist{
|
|||
char metahead[4];
|
||||
while (!feof(inFile) && !lastMeta){
|
||||
if (fread(metahead, 4, 1, inFile) != 1){
|
||||
FAIL_MSG("Could not read metadata block header - aborting!");
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Could not read metadata block header - aborting!");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -132,7 +138,7 @@ namespace Mist{
|
|||
|
||||
char metaTmp[bytes];
|
||||
if (fread(metaTmp, bytes, 1, inFile) != 1){
|
||||
FAIL_MSG("Could not read streaminfo metadata - aborting!");
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Could not read streaminfo metadata - aborting!");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -147,8 +153,8 @@ namespace Mist{
|
|||
|
||||
blockSize = (metaTmp[0] << 8 | metaTmp[1]);
|
||||
if ((metaTmp[2] << 8 | metaTmp[3]) != blockSize){
|
||||
FAIL_MSG("variable block size not supported!");
|
||||
return 1;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "variable block size not supported!");
|
||||
return false;
|
||||
}
|
||||
|
||||
sampleRate = ((metaTmp[10] << 12) | (metaTmp[11] << 4) | ((metaTmp[12] & 0xf0) >> 4));
|
||||
|
@ -174,11 +180,11 @@ namespace Mist{
|
|||
}
|
||||
|
||||
if (!sampleRate){
|
||||
FAIL_MSG("Could not get sample rate from file header");
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Could not get sample rate from file header");
|
||||
return false;
|
||||
}
|
||||
if (!channels){
|
||||
FAIL_MSG("no channel information found!");
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "no channel information found!");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,17 +32,17 @@ namespace Mist{
|
|||
|
||||
bool inputFLV::checkArguments(){
|
||||
if (config->getString("input") == "-"){
|
||||
std::cerr << "Input from stdin not yet supported" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Input from stdin not yet supported");
|
||||
return false;
|
||||
}
|
||||
if (!config->getString("streamname").size()){
|
||||
if (config->getString("output") == "-"){
|
||||
std::cerr << "Output to stdout not yet supported" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Output to stdout not yet supported");
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
if (config->getString("output") != "-"){
|
||||
std::cerr << "File output in player mode not supported" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "File output in player mode not supported");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,10 @@ namespace Mist{
|
|||
bool inputFLV::preRun(){
|
||||
// open File
|
||||
inFile = fopen(config->getString("input").c_str(), "r");
|
||||
if (!inFile){return false;}
|
||||
if (!inFile){
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Opening input '%s' failed", config->getString("input").c_str());
|
||||
return false;
|
||||
}
|
||||
struct stat statData;
|
||||
lastModTime = 0;
|
||||
if (stat(config->getString("input").c_str(), &statData) != -1){
|
||||
|
@ -78,7 +81,10 @@ namespace Mist{
|
|||
}
|
||||
|
||||
bool inputFLV::readHeader(){
|
||||
if (!inFile){return false;}
|
||||
if (!inFile){
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Reading header for '%s' failed: Could not open input stream", config->getString("input").c_str());
|
||||
return false;
|
||||
}
|
||||
meta.reInit(isSingular() ? streamName : "");
|
||||
// Create header file from FLV data
|
||||
Util::fseek(inFile, 13, SEEK_SET);
|
||||
|
@ -128,13 +134,14 @@ namespace Mist{
|
|||
}
|
||||
}
|
||||
if (feof(inFile)){
|
||||
Util::logExitReason(ER_CLEAN_EOF, "Reached EOF");
|
||||
thisPacket.null();
|
||||
return;
|
||||
}
|
||||
if (FLV::Parse_Error){
|
||||
FLV::Parse_Error = false;
|
||||
tmpTag = FLV::Tag();
|
||||
FAIL_MSG("FLV error @ %" PRIu64 ": %s", lastBytePos, FLV::Error_Str.c_str());
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "FLV error @ %" PRIu64 ": %s", lastBytePos, FLV::Error_Str.c_str());
|
||||
thisPacket.null();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -27,27 +27,27 @@ namespace Mist{
|
|||
|
||||
streamName = config->getString("streamname");
|
||||
if (streamName.find_first_of("+ ") == std::string::npos){
|
||||
FAIL_MSG("Folder input requires a + or space in the stream name.");
|
||||
return 1;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Folder input requires a + or space in the stream name.");
|
||||
return exitAndLogReason();
|
||||
}
|
||||
|
||||
std::string folder = config->getString("input");
|
||||
if (folder[folder.size() - 1] != '/'){
|
||||
FAIL_MSG("Input path must end in a forward slash.");
|
||||
return 1;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Input path must end in a forward slash.");
|
||||
return exitAndLogReason();
|
||||
}
|
||||
|
||||
std::string folder_noslash = folder.substr(0, folder.size() - 1);
|
||||
struct stat fileCheck;
|
||||
if (stat(folder_noslash.c_str(), &fileCheck) != 0 || !S_ISDIR(fileCheck.st_mode)){
|
||||
FAIL_MSG("Folder input requires a folder as input.");
|
||||
return 1;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Folder input requires a folder as input.");
|
||||
return exitAndLogReason();
|
||||
}
|
||||
|
||||
std::string path = folder + streamName.substr(streamName.find_first_of("+ ") + 1);
|
||||
if (stat(path.c_str(), &fileCheck) != 0 || S_ISDIR(fileCheck.st_mode)){
|
||||
FAIL_MSG("File not found: %s", path.c_str());
|
||||
return 1;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "File not found: %s", path.c_str());
|
||||
return exitAndLogReason();
|
||||
}
|
||||
|
||||
Util::startInput(streamName, path, false);
|
||||
|
|
|
@ -66,7 +66,7 @@ namespace Mist{
|
|||
bool InputH264::checkArguments(){
|
||||
std::string input = config->getString("input");
|
||||
if (input != "-" && input.substr(0, 10) != "h264-exec:"){
|
||||
FAIL_MSG("Unsupported input type: %s", input.c_str());
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Unsupported input type: %s", input.c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -740,7 +740,10 @@ namespace Mist{
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!initPlaylist(config->getString("input"), false)){return false;}
|
||||
if (!initPlaylist(config->getString("input"), false)){
|
||||
Util::logExitReason(ER_UNKNOWN, "Failed to load HLS playlist, aborting");
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the playlist is of event type, init the amount of segments in the playlist
|
||||
if (isLiveDVR){
|
||||
|
@ -756,7 +759,7 @@ namespace Mist{
|
|||
|
||||
void inputHLS::parseStreamHeader(){
|
||||
if (!initPlaylist(config->getString("input"))){
|
||||
FAIL_MSG("Failed to load HLS playlist, aborting");
|
||||
Util::logExitReason(ER_UNKNOWN, "Failed to load HLS playlist, aborting");
|
||||
return;
|
||||
}
|
||||
meta.reInit(isSingular() ? streamName : "", false);
|
||||
|
@ -1195,7 +1198,7 @@ namespace Mist{
|
|||
tsStream.getPacket(tid, thisPacket);
|
||||
}
|
||||
if (!thisPacket){
|
||||
FAIL_MSG("Could not getNext TS packet!");
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Could not getNext TS packet!");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1256,7 +1259,7 @@ namespace Mist{
|
|||
|
||||
// Nothing works!
|
||||
// HLS input will now quit trying to prevent severe mental depression.
|
||||
INFO_MSG("No packets can be read - exhausted all playlists");
|
||||
Util::logExitReason(ER_CLEAN_EOF, "No packets can be read - exhausted all playlists");
|
||||
thisPacket.null();
|
||||
return;
|
||||
}
|
||||
|
@ -1481,14 +1484,14 @@ namespace Mist{
|
|||
INFO_MSG("Downloading main playlist file from '%s'", uri.c_str());
|
||||
HTTP::URIReader plsDL;
|
||||
if (!plsDL.open(playlistRootPath) || !plsDL){
|
||||
FAIL_MSG("Could not open main playlist, aborting");
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Could not open main playlist, aborting");
|
||||
return false;
|
||||
}
|
||||
char * dataPtr;
|
||||
size_t dataLen;
|
||||
plsDL.readAll(dataPtr, dataLen);
|
||||
if (!dataLen){
|
||||
FAIL_MSG("Could not download main playlist, aborting.");
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Could not download main playlist, aborting.");
|
||||
return false;
|
||||
}
|
||||
urlSource.str(std::string(dataPtr, dataLen));
|
||||
|
@ -1503,7 +1506,7 @@ namespace Mist{
|
|||
}
|
||||
fileSource.open(playlistLocation.c_str());
|
||||
if (!fileSource.good()){
|
||||
FAIL_MSG("Could not open playlist (%s): %s", strerror(errno), playlistLocation.c_str());
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Could not open playlist (%s): %s", strerror(errno), playlistLocation.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,17 +24,17 @@ namespace Mist{
|
|||
|
||||
bool inputISMV::checkArguments(){
|
||||
if (config->getString("input") == "-"){
|
||||
std::cerr << "Input from stdin not yet supported" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Input from stdin not yet supported");
|
||||
return false;
|
||||
}
|
||||
if (!config->getString("streamname").size()){
|
||||
if (config->getString("output") == "-"){
|
||||
std::cerr << "Output to stdout not yet supported" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Output to stdout not yet supported");
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
if (config->getString("output") != "-"){
|
||||
std::cerr << "File output in player mode not supported" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "File output in player mode not supported");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -43,11 +43,18 @@ namespace Mist{
|
|||
|
||||
bool inputISMV::preRun(){
|
||||
inFile = fopen(config->getString("input").c_str(), "r");
|
||||
return inFile; // True if not null
|
||||
if (!inFile){
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Opening input '%s' failed", config->getString("input").c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool inputISMV::readHeader(){
|
||||
if (!inFile){return false;}
|
||||
if (!inFile){
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Reading header for '%s' failed: Could not open input stream", config->getString("input").c_str());
|
||||
return false;
|
||||
}
|
||||
meta.reInit(streamName);
|
||||
// parse ismv header
|
||||
fseek(inFile, 0, SEEK_SET);
|
||||
|
@ -189,7 +196,10 @@ namespace Mist{
|
|||
MP4::MOOF moof;
|
||||
moof.read(inFile);
|
||||
|
||||
if (feof(inFile)){return false;}
|
||||
if (feof(inFile)){
|
||||
Util::logExitReason(ER_CLEAN_EOF, "Reached EOF");
|
||||
return false;
|
||||
}
|
||||
|
||||
MP4::TRAF trafBox = moof.getChild<MP4::TRAF>();
|
||||
for (size_t j = 0; j < trafBox.getContentCount(); j++){
|
||||
|
@ -205,7 +215,11 @@ namespace Mist{
|
|||
}
|
||||
|
||||
MP4::skipBox(inFile);
|
||||
return !feof(inFile);
|
||||
if (feof(inFile)){
|
||||
Util::logExitReason(ER_CLEAN_EOF, "Reached EOF");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void inputISMV::bufferFragmentData(size_t trackId, uint32_t keyNum){
|
||||
|
@ -230,7 +244,7 @@ namespace Mist{
|
|||
if (trafBox.getContent(j).isType("trun")){trunBox = (MP4::TRUN &)trafBox.getContent(j);}
|
||||
if (trafBox.getContent(j).isType("tfhd")){
|
||||
if (M.getID(trackId) != ((MP4::TFHD &)trafBox.getContent(j)).getTrackID()){
|
||||
FAIL_MSG("Trackids do not match");
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Trackids do not match");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,17 +25,17 @@ namespace Mist{
|
|||
|
||||
bool inputMP3::checkArguments(){
|
||||
if (config->getString("input") == "-"){
|
||||
std::cerr << "Input from stdin not yet supported" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Input from stdin not yet supported");
|
||||
return false;
|
||||
}
|
||||
if (!config->getString("streamname").size()){
|
||||
if (config->getString("output") == "-"){
|
||||
std::cerr << "Output to stdout not yet supported" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Output to stdout not yet supported");
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
if (config->getString("output") != "-"){
|
||||
std::cerr << "File output in player mode not supported" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "File output in player mode not supported");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -45,12 +45,18 @@ namespace Mist{
|
|||
bool inputMP3::preRun(){
|
||||
// open File
|
||||
inFile = fopen(config->getString("input").c_str(), "r");
|
||||
if (!inFile){return false;}
|
||||
if (!inFile){
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Opening input '%s' failed", config->getString("input").c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool inputMP3::readHeader(){
|
||||
if (!inFile){return false;}
|
||||
if (!inFile){
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Reading header for '%s' failed: Could not open input stream", config->getString("input").c_str());
|
||||
return false;
|
||||
}
|
||||
meta.reInit(isSingular() ? streamName : "");
|
||||
size_t tNum = meta.addTrack();
|
||||
meta.setID(tNum, tNum);
|
||||
|
@ -93,7 +99,10 @@ namespace Mist{
|
|||
static char packHeader[3000];
|
||||
size_t filePos = ftell(inFile);
|
||||
size_t read = fread(packHeader, 1, 3000, inFile);
|
||||
if (!read){return;}
|
||||
if (!read){
|
||||
Util::logExitReason(ER_CLEAN_EOF, "Reached EOF");
|
||||
return;
|
||||
}
|
||||
if (packHeader[0] != 0xFF || (packHeader[1] & 0xE0) != 0xE0){
|
||||
// Find the first occurence of sync byte
|
||||
char *i = (char *)memchr(packHeader, (char)0xFF, read);
|
||||
|
@ -107,7 +116,7 @@ namespace Mist{
|
|||
}
|
||||
}
|
||||
if (!offset){
|
||||
FAIL_MSG("Sync byte not found from offset %zu", filePos);
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Sync byte not found from offset %zu", filePos);
|
||||
return;
|
||||
}
|
||||
filePos += offset;
|
||||
|
|
|
@ -127,17 +127,17 @@ namespace Mist{
|
|||
|
||||
bool inputMP4::checkArguments(){
|
||||
if (config->getString("input") == "-"){
|
||||
std::cerr << "Input from stdin not yet supported" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Input from stdin not yet supported");
|
||||
return false;
|
||||
}
|
||||
if (!config->getString("streamname").size()){
|
||||
if (config->getString("output") == "-"){
|
||||
std::cerr << "Output to stdout not yet supported" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Output to stdout not yet supported");
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
if (config->getString("output") != "-"){
|
||||
std::cerr << "File output in player mode not supported" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "File output in player mode not supported");
|
||||
return false;
|
||||
}
|
||||
streamName = config->getString("streamname");
|
||||
|
@ -148,9 +148,12 @@ namespace Mist{
|
|||
bool inputMP4::preRun(){
|
||||
// open File
|
||||
inFile.open(config->getString("input"));
|
||||
if (!inFile){return false;}
|
||||
if (!inFile){
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Could not open URL or contains no data");
|
||||
return false;
|
||||
}
|
||||
if (!inFile.isSeekable()){
|
||||
FAIL_MSG("MP4 input only supports seekable data sources, for now, and this source is not seekable: %s", config->getString("input").c_str());
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "MP4 input only supports seekable data sources, for now, and this source is not seekable: %s", config->getString("input").c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -168,7 +171,7 @@ namespace Mist{
|
|||
|
||||
bool inputMP4::readHeader(){
|
||||
if (!inFile){
|
||||
Util::logExitReason("Could not open input file");
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Reading header for '%s' failed: Could not open input stream", config->getString("input").c_str());
|
||||
return false;
|
||||
}
|
||||
bool hasMoov = false;
|
||||
|
@ -183,7 +186,7 @@ namespace Mist{
|
|||
while (readBuffer.size() < 16 && inFile && keepRunning()){inFile.readSome(16, *this);}
|
||||
//Failed? Abort.
|
||||
if (readBuffer.size() < 16){
|
||||
FAIL_MSG("Could not read box header from input!");
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Could not read box header from input!");
|
||||
break;
|
||||
}
|
||||
//Box type is always on bytes 5-8 from the start of a box
|
||||
|
@ -192,7 +195,7 @@ namespace Mist{
|
|||
if (boxType == "moov"){
|
||||
while (readBuffer.size() < boxSize && inFile && keepRunning()){inFile.readSome(boxSize-readBuffer.size(), *this);}
|
||||
if (readBuffer.size() < boxSize){
|
||||
FAIL_MSG("Could not read entire MOOV box into memory");
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Could not read entire MOOV box into memory");
|
||||
break;
|
||||
}
|
||||
MP4::Box moovBox(readBuffer, false);
|
||||
|
@ -221,8 +224,11 @@ namespace Mist{
|
|||
}
|
||||
|
||||
if (!hasMoov){
|
||||
if (!inFile){Util::logExitReason("URIReader for source file was disconnected!");}
|
||||
Util::logExitReason("No MOOV box found in source file; aborting!");
|
||||
if (!inFile){
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Reading header for '%s' failed: URIReader for source file was disconnected!", config->getString("input").c_str());
|
||||
}else{
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Reading header for '%s' failed: No MOOV box found in source file; aborting!", config->getString("input").c_str());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -515,7 +521,7 @@ namespace Mist{
|
|||
INFO_MSG("Buffer contains %" PRIu64 "-%" PRIu64 ", but we need %" PRIu64 "; seeking!", readPos, readPos + readBuffer.size(), curPart.bpos);
|
||||
readBuffer.truncate(0);
|
||||
if (!inFile.seek(curPart.bpos)){
|
||||
FAIL_MSG("seek unsuccessful @bpos %" PRIu64 ": %s", curPart.bpos, strerror(errno));
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "seek unsuccessful @bpos %" PRIu64 ": %s", curPart.bpos, strerror(errno));
|
||||
thisPacket.null();
|
||||
return;
|
||||
}
|
||||
|
@ -536,7 +542,7 @@ namespace Mist{
|
|||
FAIL_MSG("Read unsuccessful at %" PRIu64 ", seeking to retry...", readPos+readBuffer.size());
|
||||
readBuffer.truncate(0);
|
||||
if (!inFile.seek(curPart.bpos)){
|
||||
FAIL_MSG("seek unsuccessful @bpos %" PRIu64 ": %s", curPart.bpos, strerror(errno));
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "seek unsuccessful @bpos %" PRIu64 ": %s", curPart.bpos, strerror(errno));
|
||||
thisPacket.null();
|
||||
return;
|
||||
}
|
||||
|
@ -545,7 +551,7 @@ namespace Mist{
|
|||
inFile.readSome((curPart.bpos+curPart.size) - (readPos+readBuffer.size()), *this);
|
||||
}
|
||||
if (readPos+readBuffer.size() < curPart.bpos+curPart.size){
|
||||
FAIL_MSG("Read retry unsuccessful at %" PRIu64 ", aborting", readPos+readBuffer.size());
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Read retry unsuccessful at %" PRIu64 ", aborting", readPos+readBuffer.size());
|
||||
thisPacket.null();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -54,7 +54,10 @@ namespace Mist{
|
|||
bool inputOGG::preRun(){
|
||||
// open File
|
||||
inFile = fopen(config->getString("input").c_str(), "r");
|
||||
if (!inFile){return false;}
|
||||
if (!inFile){
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Opening input '%s' failed", config->getString("input").c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -142,7 +145,7 @@ namespace Mist{
|
|||
size_t len = myPage.getSegmentLen(i);
|
||||
theora::header tmpHead((char *)myPage.getSegment(i), len);
|
||||
if (!tmpHead.isHeader()){// not copying the header anymore, should this check isHeader?
|
||||
FAIL_MSG("Theora Header read failed!");
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Reading header for '%s' failed: Theora header read failed", config->getString("input").c_str());
|
||||
return false;
|
||||
}
|
||||
switch (tmpHead.getHeaderType()){
|
||||
|
@ -174,7 +177,7 @@ namespace Mist{
|
|||
size_t len = myPage.getSegmentLen(i);
|
||||
vorbis::header tmpHead((char *)myPage.getSegment(i), len);
|
||||
if (!tmpHead.isHeader()){
|
||||
FAIL_MSG("Header read failed!");
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Reading header for '%s' failed: Header read failed", config->getString("input").c_str());
|
||||
return false;
|
||||
}
|
||||
switch (tmpHead.getHeaderType()){
|
||||
|
|
|
@ -22,17 +22,17 @@ namespace Mist{
|
|||
|
||||
bool inputPlaylist::checkArguments(){
|
||||
if (config->getString("input") == "-"){
|
||||
std::cerr << "Input from stdin not supported" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Input from stdin not yet supported");
|
||||
return false;
|
||||
}
|
||||
if (!config->getString("streamname").size()){
|
||||
if (config->getString("output") == "-"){
|
||||
std::cerr << "Output to stdout not supported" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Output to stdout not yet supported");
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
if (config->getString("output") != "-"){
|
||||
std::cerr << "File output not supported" << std::endl;
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "File output in player mode not supported");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ namespace Mist{
|
|||
killSwitch.reload(streamName, (size_t)INVALID_TRACK_ID, (uint8_t)(COMM_STATUS_ACTIVE | COMM_STATUS_DONOTTRACK));
|
||||
while (config->is_active){
|
||||
if (killSwitch && killSwitch.getStatus() & COMM_STATUS_REQDISCONNECT){
|
||||
Util::logExitReason("buffer requested shutdown");
|
||||
Util::logExitReason(ER_CLEAN_LIVE_BUFFER_REQ, "buffer requested shutdown");
|
||||
config->is_active = false;
|
||||
break;
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ namespace Mist{
|
|||
wallTime = wTime->tm_hour * 60 + wTime->tm_min;
|
||||
reloadPlaylist();
|
||||
if (!playlist.size()){
|
||||
Util::logExitReason("No entries in playlist");
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "No entries in playlist");
|
||||
return;
|
||||
}
|
||||
++playlistIndex;
|
||||
|
@ -112,7 +112,7 @@ namespace Mist{
|
|||
seenValidEntry = true;
|
||||
while (Util::Procs::isRunning(spawn_pid) && config->is_active){
|
||||
if (killSwitch && killSwitch.getStatus() & COMM_STATUS_REQDISCONNECT){
|
||||
Util::logExitReason("buffer requested shutdown");
|
||||
Util::logExitReason(ER_CLEAN_LIVE_BUFFER_REQ, "buffer requested shutdown");
|
||||
config->is_active = false;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -122,12 +122,12 @@ namespace Mist{
|
|||
bool InputRTSP::checkArguments(){
|
||||
const std::string &inpt = config->getString("input");
|
||||
if (inpt.substr(0, 7) != "rtsp://"){
|
||||
FAIL_MSG("Unsupported RTSP URL: '%s'", inpt.c_str());
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Unsupported RTSP URL: '%s'", inpt.c_str());
|
||||
return false;
|
||||
}
|
||||
const std::string &transport = config->getString("transport");
|
||||
if (transport != "TCP" && transport != "UDP" && transport != "tcp" && transport != "udp"){
|
||||
FAIL_MSG("Not a supported transport mode: %s", transport.c_str());
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Not a supported transport mode: %s", transport.c_str());
|
||||
return false;
|
||||
}
|
||||
if (transport == "UDP" || transport == "udp"){TCPmode = false;}
|
||||
|
@ -142,7 +142,11 @@ namespace Mist{
|
|||
bool InputRTSP::openStreamSource(){
|
||||
tcpCon.open(url.host, url.getPort(), false);
|
||||
mainConn = &tcpCon;
|
||||
return tcpCon;
|
||||
if (!tcpCon){
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Opening TCP socket `%s:%s` failed", url.host.c_str(), url.getPort());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void InputRTSP::parseStreamHeader(){
|
||||
|
@ -152,7 +156,7 @@ namespace Mist{
|
|||
extraHeaders["Accept"] = "application/sdp";
|
||||
sendCommand("DESCRIBE", url.getUrl(), "", &extraHeaders);
|
||||
if (!tcpCon || !seenSDP){
|
||||
FAIL_MSG("Could not get stream description!");
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Could not get stream description!");
|
||||
return;
|
||||
}
|
||||
if (sdpState.tracks.size()){
|
||||
|
@ -178,7 +182,7 @@ namespace Mist{
|
|||
atLeastOne = true;
|
||||
continue;
|
||||
}
|
||||
FAIL_MSG("Could not setup track %s!", M.getTrackIdentifier(it->first).c_str());
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Could not setup track %s!", M.getTrackIdentifier(it->first).c_str());
|
||||
tcpCon.close();
|
||||
return;
|
||||
}
|
||||
|
@ -214,7 +218,7 @@ namespace Mist{
|
|||
if (statComm){
|
||||
if (statComm.getStatus() & COMM_STATUS_REQDISCONNECT){
|
||||
config->is_active = false;
|
||||
Util::logExitReason("received shutdown request from controller");
|
||||
Util::logExitReason(ER_CLEAN_CONTROLLER_REQ, "received shutdown request from controller");
|
||||
return;
|
||||
}
|
||||
uint64_t now = Util::bootSecs();
|
||||
|
@ -229,7 +233,7 @@ namespace Mist{
|
|||
}
|
||||
}
|
||||
if (!tcpCon){
|
||||
Util::logExitReason("TCP connection closed");
|
||||
Util::logExitReason(ER_CLEAN_REMOTE_CLOSE, "TCP connection closed");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -402,7 +406,7 @@ namespace Mist{
|
|||
userSelect[idx].reload(streamName, idx, COMM_STATUS_ACTIVE | COMM_STATUS_SOURCE | COMM_STATUS_DONOTTRACK);
|
||||
}
|
||||
if (userSelect[idx].getStatus() & COMM_STATUS_REQDISCONNECT){
|
||||
Util::logExitReason("buffer requested shutdown");
|
||||
Util::logExitReason(ER_CLEAN_LIVE_BUFFER_REQ, "buffer requested shutdown");
|
||||
tcpCon.close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ namespace Mist{
|
|||
bool InputSDP::checkArguments(){
|
||||
const std::string &inpt = config->getString("input");
|
||||
if (inpt.substr(inpt.length() - 4) != ".sdp"){
|
||||
FAIL_MSG("Expected a SDP file but received: '%s'", inpt.c_str());
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Expected a SDP file but received: '%s'", inpt.c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -88,13 +88,17 @@ namespace Mist{
|
|||
const std::string &inpt = config->getString("input");
|
||||
reader.open(inpt);
|
||||
// Will return false if it cant open file or it is EOF
|
||||
return reader;
|
||||
if (!reader){
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Opening input '%s' failed", config->getString("input").c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Gets and parses the SDP file
|
||||
void InputSDP::parseStreamHeader(){
|
||||
if (!reader){
|
||||
FAIL_MSG("Connection lost with input. Could not get stream description!");
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Connection lost with input. Could not get stream description!");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -206,7 +210,7 @@ namespace Mist{
|
|||
if (statComm){
|
||||
if (statComm.getStatus() == COMM_STATUS_REQDISCONNECT){
|
||||
config->is_active = false;
|
||||
Util::logExitReason("received shutdown request from controller");
|
||||
Util::logExitReason(ER_CLEAN_CONTROLLER_REQ, "received shutdown request from controller");
|
||||
return;
|
||||
}
|
||||
uint64_t now = Util::bootSecs();
|
||||
|
@ -312,7 +316,7 @@ namespace Mist{
|
|||
userSelect[idx].reload(streamName, idx, COMM_STATUS_ACTIVE | COMM_STATUS_SOURCE | COMM_STATUS_DONOTTRACK);
|
||||
}
|
||||
if (userSelect[idx].getStatus() == COMM_STATUS_REQDISCONNECT){
|
||||
Util::logExitReason("buffer requested shutdown");
|
||||
Util::logExitReason(ER_CLEAN_LIVE_BUFFER_REQ, "buffer requested shutdown");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace Mist{
|
|||
fileSource.close();
|
||||
fileSource.open(config->getString("input").c_str());
|
||||
if (!fileSource.is_open()){
|
||||
FAIL_MSG("Could not open file %s: %s", config->getString("input").c_str(), strerror(errno));
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Could not open file %s: %s", config->getString("input").c_str(), strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -25,7 +25,7 @@ namespace Mist{
|
|||
|
||||
bool InputSrt::checkArguments(){
|
||||
if (config->getString("input") == "-"){
|
||||
FAIL_MSG("Reading from standard input not yet supported");
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Input from stdin not yet supported");
|
||||
return false;
|
||||
}else{
|
||||
preRun();
|
||||
|
@ -33,12 +33,12 @@ namespace Mist{
|
|||
|
||||
if (!config->getString("streamname").size()){
|
||||
if (config->getString("output") == "-"){
|
||||
FAIL_MSG("Writing to standard output not yet supported");
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Output to stdout not yet supported");
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
if (config->getString("output") != "-"){
|
||||
FAIL_MSG("File output in player mode not supported");
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "File output in player mode not supported");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,10 @@ namespace Mist{
|
|||
}
|
||||
|
||||
bool InputSrt::readHeader(){
|
||||
if (!fileSource.good()){return false;}
|
||||
if (!fileSource.good()){
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Reading header for '%s' failed: Could not open input stream", config->getString("input").c_str());
|
||||
return false;
|
||||
}
|
||||
size_t idx = meta.addTrack();
|
||||
meta.setID(idx, 1);
|
||||
meta.setType(idx, "meta");
|
||||
|
|
|
@ -353,7 +353,11 @@ namespace Mist{
|
|||
FILE * inFile = fopen(inCfg.c_str() + 9, "r");
|
||||
reader.open(fileno(inFile));
|
||||
standAlone = false;
|
||||
return inFile;
|
||||
if (!inFile){
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Opening input '%s' failed", inCfg.c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//Anything else, read through URIReader
|
||||
HTTP::URL url = HTTP::localURIResolver().link(inCfg);
|
||||
|
@ -361,7 +365,11 @@ namespace Mist{
|
|||
if (url.protocol == "https-ts"){url.protocol = "https";}
|
||||
reader.open(url);
|
||||
standAlone = reader.isSeekable();
|
||||
return reader;
|
||||
if (!reader){
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Opening input '%s' failed", inCfg.c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void inputTS::dataCallback(const char *ptr, size_t size){
|
||||
|
@ -387,7 +395,10 @@ namespace Mist{
|
|||
/// for a specific track to metadata. After the entire stream has been read,
|
||||
/// it writes the remaining metadata.
|
||||
bool inputTS::readHeader(){
|
||||
if (!reader){return false;}
|
||||
if (!reader){
|
||||
Util::logExitReason(ER_READ_START_FAILURE, "Reading header for '%s' failed: Could not open input stream", config->getString("input").c_str());
|
||||
return false;
|
||||
}
|
||||
meta.reInit(isSingular() ? streamName : "");
|
||||
TS::Packet packet; // to analyse and extract data
|
||||
DTSC::Packet headerPack;
|
||||
|
@ -471,7 +482,7 @@ namespace Mist{
|
|||
}
|
||||
|
||||
if (!thisPacket){
|
||||
INFO_MSG("Could not getNext TS packet!");
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Could not getNext TS packet!");
|
||||
return;
|
||||
}
|
||||
tsStream.initializeMetadata(meta);
|
||||
|
@ -583,7 +594,7 @@ namespace Mist{
|
|||
}
|
||||
if (!reader){
|
||||
config->is_active = false;
|
||||
Util::logExitReason("end of streamed input");
|
||||
Util::logExitReason(ER_CLEAN_EOF, "end of streamed input");
|
||||
return;
|
||||
}
|
||||
}else{
|
||||
|
@ -635,7 +646,7 @@ namespace Mist{
|
|||
if (statComm){
|
||||
if (statComm.getStatus() & COMM_STATUS_REQDISCONNECT){
|
||||
config->is_active = false;
|
||||
Util::logExitReason("received shutdown request from controller");
|
||||
Util::logExitReason(ER_CLEAN_CONTROLLER_REQ, "received shutdown request from controller");
|
||||
return;
|
||||
}
|
||||
uint64_t now = Util::bootSecs();
|
||||
|
@ -654,7 +665,7 @@ namespace Mist{
|
|||
if (hasStarted && !threadTimer.size()){
|
||||
if (!isAlwaysOn()){
|
||||
config->is_active = false;
|
||||
Util::logExitReason("no active threads and we had input in the past");
|
||||
Util::logExitReason(ER_CLEAN_INACTIVE, "no active threads and we had input in the past");
|
||||
return;
|
||||
}else{
|
||||
liveStream.clear();
|
||||
|
@ -686,7 +697,7 @@ namespace Mist{
|
|||
if (Util::bootSecs() - noDataSince > 20){
|
||||
if (!isAlwaysOn()){
|
||||
config->is_active = false;
|
||||
Util::logExitReason("no packets received for 20 seconds");
|
||||
Util::logExitReason(ER_CLEAN_INACTIVE, "no packets received for 20 seconds");
|
||||
return;
|
||||
}else{
|
||||
noDataSince = Util::bootSecs();
|
||||
|
|
|
@ -167,7 +167,7 @@ namespace Mist{
|
|||
standAlone = false;
|
||||
HTTP::URL u(source);
|
||||
if (u.protocol != "rist"){
|
||||
FAIL_MSG("Input protocol must begin with rist://");
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "Input protocol must begin with rist://");
|
||||
return false;
|
||||
}
|
||||
std::map<std::string, std::string> arguments;
|
||||
|
@ -184,7 +184,7 @@ namespace Mist{
|
|||
while (!hasRaw && config->is_active){
|
||||
Util::sleep(50);
|
||||
if (!bufferActive()){
|
||||
Util::logExitReason("Buffer shut down");
|
||||
Util::logExitReason(ER_SHM_LOST, "Buffer shut down");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -198,7 +198,7 @@ namespace Mist{
|
|||
}else{
|
||||
Util::sleep(50);
|
||||
if (!bufferActive()){
|
||||
Util::logExitReason("Buffer shut down");
|
||||
Util::logExitReason(ER_SHM_LOST, "Buffer shut down");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -224,7 +224,7 @@ namespace Mist{
|
|||
|
||||
void inputTSRIST::onFail(const std::string & msg){
|
||||
FAIL_MSG("%s", msg.c_str());
|
||||
Util::logExitReason(msg.c_str());
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, msg.c_str());
|
||||
}
|
||||
|
||||
bool inputTSRIST::openStreamSource(){
|
||||
|
|
|
@ -229,9 +229,9 @@ namespace Mist{
|
|||
if (!thisPacket){
|
||||
if (srtConn){
|
||||
INFO_MSG("Could not getNext TS packet!");
|
||||
Util::logExitReason("internal TS parser error");
|
||||
Util::logExitReason(ER_FORMAT_SPECIFIC, "internal TS parser error");
|
||||
}else{
|
||||
Util::logExitReason("SRT connection close");
|
||||
Util::logExitReason(ER_CLEAN_REMOTE_CLOSE, "SRT connection close");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue