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:
Marco 2022-12-22 13:41:10 +01:00 committed by Thulinma
parent a16d98b7b2
commit b0d4422d27
47 changed files with 493 additions and 256 deletions

View file

@ -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();

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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){

View file

@ -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();

View file

@ -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;
}

View file

@ -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());

View file

@ -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;

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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;

View file

@ -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());
}
}

View file

@ -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;
}
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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()){

View file

@ -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;
}

View file

@ -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();
}
}

View file

@ -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");
}
}

View file

@ -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");

View file

@ -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();

View file

@ -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(){

View file

@ -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;
}