Merge branch 'development' into LTS_development

# Conflicts:
#	CMakeLists.txt
#	src/input/input_buffer.cpp
This commit is contained in:
Thulinma 2017-07-22 18:55:12 +02:00
commit d42bf9777e
23 changed files with 381 additions and 27 deletions

View file

@ -1,5 +1,6 @@
#include "analyser_dtsc.h"
#include <mist/h264.h>
#include <iomanip>
void AnalyserDTSC::init(Util::Config &conf){
Analyser::init(conf);
@ -34,6 +35,15 @@ bool AnalyserDTSC::parsePacket(){
std::cout << "DTSCv2 packet (Track " << P.getTrackId() << ", time " << P.getTime()
<< "): " << P.getScan().toPrettyString() << std::endl;
}
if (detail >= 8){
char * payDat;
unsigned int payLen;
P.getString("data", payDat, payLen);
for (uint64_t i = 0; i < payLen; ++i){
if ((i % 32) == 0){std::cout << std::endl;}
std::cout << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)payDat[i];
}
}
break;
}
case DTSC::DTSC_HEAD:{

View file

@ -116,7 +116,7 @@ namespace Mist {
return 0;
}
if (!setup()) {
if (!checkArguments()) {
FAIL_MSG("Setup failed - exiting");
return 0;
}
@ -141,6 +141,7 @@ namespace Mist {
pid_t pid = fork();
if (pid == 0){
if (needsLock()){playerLock.close();}
if (!preRun()){return 0;}
return run();
}
if (pid == -1){

View file

@ -27,17 +27,18 @@ namespace Mist {
virtual bool needsLock(){return true;}
protected:
static void callbackWrapper(char * data, size_t len, unsigned int id);
virtual bool setup() = 0;
virtual bool checkArguments() = 0;
virtual bool readHeader() = 0;
virtual bool preRun(){return true;}
virtual bool readExistingHeader();
virtual bool atKeyFrame();
virtual void getNext(bool smart = true) {};
virtual void getNext(bool smart = true) {}
virtual void seek(int seekTime){};
virtual void finish();
virtual bool keepRunning();
virtual bool openStreamSource() { return false; };
virtual void closeStreamSource() {};
virtual void parseStreamHeader() {};
virtual bool openStreamSource() { return false; }
virtual void closeStreamSource() {}
virtual void parseStreamHeader() {}
void play(int until = 0);
void playOnce();
void quitPlay();

View file

@ -935,7 +935,7 @@ namespace Mist {
}
}
bool inputBuffer::setup() {
bool inputBuffer::preRun() {
lastReTime = Util::epoch(); /*LTS*/
std::string strName = config->getString("streamname");
Util::sanitizeName(strName);

View file

@ -21,7 +21,8 @@ namespace Mist {
IPC::semaphore * liveMeta;
protected:
//Private Functions
bool setup();
bool preRun();
bool checkArguments(){return true;}
void updateMeta();
bool readHeader();
void getNext(bool smart = true);

View file

@ -58,7 +58,7 @@ namespace Mist {
}
bool inputDTSC::needsLock(){
return config->getString("input").substr(0, 7) != "dtsc://";
return config->getString("input").substr(0, 7) != "dtsc://" && config->getString("input") != "-";
}
void parseDTSCURI(const std::string & src, std::string & host, uint16_t & port, std::string & password, std::string & streamName) {
@ -121,7 +121,7 @@ namespace Mist {
}
void inputDTSC::parseStreamHeader() {
while (srcConn.connected()){
while (srcConn.connected() && config->is_active){
srcConn.spool();
if (srcConn.Received().available(8)){
if (srcConn.Received().copy(4) == "DTCM" || srcConn.Received().copy(4) == "DTSC") {
@ -158,6 +158,10 @@ namespace Mist {
bool inputDTSC::openStreamSource() {
std::string source = config->getString("input");
if (source == "-"){
srcConn = Socket::Connection(fileno(stdout),fileno(stdin));
return true;
}
if (source.find("dtsc://") == 0) {
source.erase(0, 7);
}
@ -194,14 +198,10 @@ namespace Mist {
srcConn.close();
}
bool inputDTSC::setup() {
bool inputDTSC::checkArguments() {
if (!needsLock()) {
return true;
} else {
if (config->getString("input") == "-") {
std::cerr << "Input from stdin not yet supported" << std::endl;
return false;
}
if (!config->getString("streamname").size()) {
if (config->getString("output") == "-") {
std::cerr << "Output to stdout not yet supported" << std::endl;

View file

@ -11,7 +11,7 @@ namespace Mist {
bool openStreamSource();
void closeStreamSource();
void parseStreamHeader();
bool setup();
bool checkArguments();
bool readHeader();
void getNext(bool smart = true);
void seek(int seekTime);

View file

@ -27,7 +27,7 @@ namespace Mist {
capa["codecs"][0u][1u].append("MP3");
}
bool inputFLV::setup() {
bool inputFLV::checkArguments() {
if (config->getString("input") == "-") {
std::cerr << "Input from stdin not yet supported" << std::endl;
return false;
@ -43,7 +43,10 @@ namespace Mist {
return false;
}
}
return true;
}
bool inputFLV::preRun() {
//open File
inFile = fopen(config->getString("input").c_str(), "r");
if (!inFile) {

View file

@ -8,7 +8,8 @@ namespace Mist {
inputFLV(Util::Config * cfg);
protected:
//Private Functions
bool setup();
bool checkArguments();
bool preRun();
bool readHeader();
void getNext(bool smart = true);
void seek(int seekTime);

127
src/input/input_h264.cpp Normal file
View file

@ -0,0 +1,127 @@
#include "input_h264.h"
#include <mist/h264.h>
#include <mist/mp4_generic.h>
namespace Mist{
InputH264::InputH264(Util::Config *cfg) : Input(cfg){
capa["name"] = "H264";
capa["desc"] = "H264 Annex B input";
capa["source_match"] = "h264-exec:*";
//May be set to always-on mode
capa["always_match"].append("h264-exec:*");
capa["priority"] = 0ll;
capa["codecs"][0u][0u].append("H264");
frameCount = 0;
startTime = Util::bootMS();
inputProcess = 0;
}
bool InputH264::preRun(){
if (config->getString("input") != "-"){
std::string input = config->getString("input");
const char *argv[2];
input = input.substr(10);
char *args[128];
uint8_t argCnt = 0;
char *startCh = 0;
for (char *i = (char*)input.c_str(); i <= input.data() + input.size(); ++i){
if (!*i){
if (startCh){args[argCnt++] = startCh;}
break;
}
if (*i == ' '){
if (startCh){
args[argCnt++] = startCh;
startCh = 0;
*i = 0;
}
}else{
if (!startCh){startCh = i;}
}
}
args[argCnt] = 0;
int fin = -1, fout = -1, ferr = -1;
inputProcess = Util::Procs::StartPiped(args, &fin, &fout, &ferr);
myConn = Socket::Connection(-1, fout);
}else{
myConn = Socket::Connection(fileno(stdout), fileno(stdin));
}
myConn.Received().splitter.assign("\000\000\001", 3);
myMeta.vod = false;
myMeta.live = true;
myMeta.tracks[1].type = "video";
myMeta.tracks[1].codec = "H264";
myMeta.tracks[1].trackID = 1;
waitsSinceData = 0;
return true;
}
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());
return false;
}
return true;
}
void InputH264::getNext(bool smart){
do{
if (!myConn.spool()){
Util::sleep(25);
++waitsSinceData;
if (waitsSinceData > 5000 / 25 && (waitsSinceData % 40) == 0){
WARN_MSG("No H264 data received for > 5s, killing source process");
Util::Procs::Stop(inputProcess);
}
continue;
}
waitsSinceData = 0;
uint32_t bytesToRead = myConn.Received().bytesToSplit();
if (!bytesToRead){continue;}
std::string NAL = myConn.Received().remove(bytesToRead);
uint32_t nalSize = NAL.size() - 3;
while (nalSize && NAL.data()[nalSize - 1] == 0){--nalSize;}
if (!nalSize){continue;}
uint8_t nalType = NAL.data()[0] & 0x1F;
INSANE_MSG("NAL unit, type %u, size %lu", nalType, nalSize);
if (nalType == 7 || nalType == 8){
if (nalType == 7){spsInfo = NAL.substr(0, nalSize);}
if (nalType == 8){ppsInfo = NAL.substr(0, nalSize);}
if (!myMeta.tracks[1].init.size() && spsInfo.size() && ppsInfo.size()){
h264::sequenceParameterSet sps(spsInfo.data(), spsInfo.size());
h264::SPSMeta spsChar = sps.getCharacteristics();
myMeta.tracks[1].width = spsChar.width;
myMeta.tracks[1].height = spsChar.height;
myMeta.tracks[1].fpks = spsChar.fps * 1000;
if (myMeta.tracks[1].fpks < 100 || myMeta.tracks[1].fpks > 1000000){
myMeta.tracks[1].fpks = 0;
}
MP4::AVCC avccBox;
avccBox.setVersion(1);
avccBox.setProfile(spsInfo[1]);
avccBox.setCompatibleProfiles(spsInfo[2]);
avccBox.setLevel(spsInfo[3]);
avccBox.setSPSNumber(1);
avccBox.setSPS(spsInfo);
avccBox.setPPSNumber(1);
avccBox.setPPS(ppsInfo);
myMeta.tracks[1].init = std::string(avccBox.payload(), avccBox.payloadSize());
}
continue;
}
if (myMeta.tracks[1].init.size()){
uint64_t ts = Util::bootMS() - startTime;
if (myMeta.tracks[1].fpks){ts = frameCount * (1000000 / myMeta.tracks[1].fpks);}
thisPacket.genericFill(ts, 0, 1, 0, 0, 0, h264::isKeyframe(NAL.data(), nalSize));
thisPacket.appendNal(NAL.data(), nalSize, nalSize);
++frameCount;
return;
}
}while (myConn && (inputProcess == 0 || Util::Procs::childRunning(inputProcess)));
if (inputProcess){myConn.close();}
}
}

33
src/input/input_h264.h Normal file
View file

@ -0,0 +1,33 @@
#include "input.h"
#include <mist/dtsc.h>
#include <mist/procs.h>
namespace Mist{
class InputH264 : public Input{
public:
InputH264(Util::Config *cfg);
protected:
bool checkArguments();
bool preRun();
void getNext(bool smart = true);
Socket::Connection myConn;
std::string ppsInfo;
std::string spsInfo;
uint64_t frameCount;
// Empty defaults
bool readHeader(){return true;}
bool openStreamSource(){return true;}
void closeStreamSource(){}
void parseStreamHeader(){}
void seek(int seekTime){}
void trackSelect(std::string trackSpec){}
bool needsLock(){return false;}
uint64_t startTime;
pid_t inputProcess;
uint32_t waitsSinceData;
};
}
typedef Mist::InputH264 mistIn;

View file

@ -21,7 +21,7 @@ namespace Mist {
timestamp = 0;
}
bool inputMP3::setup() {
bool inputMP3::checkArguments() {
if (config->getString("input") == "-") {
std::cerr << "Input from stdin not yet supported" << std::endl;
return false;
@ -37,7 +37,10 @@ namespace Mist {
return false;
}
}
return true;
}
bool inputMP3::preRun() {
//open File
inFile = fopen(config->getString("input").c_str(), "r");
if (!inFile) {

View file

@ -16,7 +16,8 @@ namespace Mist {
inputMP3(Util::Config * cfg);
protected:
//Private Functions
bool setup();
bool checkArguments();
bool preRun();
bool readHeader();
void getNext(bool smart = true);
void seek(int seekTime);

View file

@ -53,12 +53,15 @@ namespace Mist {
capa["codecs"][0u][1u].append("opus");
}
bool inputOGG::setup(){
bool inputOGG::checkArguments(){
if (config->getString("input") == "-"){
std::cerr << "Input from stream not yet supported" << std::endl;
return false;
}
return true;
}
bool inputOGG::preRun(){
//open File
inFile = fopen(config->getString("input").c_str(), "r");
if (!inFile){

View file

@ -70,7 +70,8 @@ namespace Mist {
inputOGG(Util::Config * cfg);
protected:
//Private Functions
bool setup();
bool checkArguments();
bool preRun();
bool readHeader();
position seekFirstData(long long unsigned int tid);
void getNext(bool smart = true);