
- Added support for new "NowMs" field that holds up to where no new packets are guaranteed to show up, in order to lower latency. - Added support for JSON tracks over all TS-based protocols (input and output) - Added support for AMF metadata conversion to JSON (RTMP/FLV input) - Fixed MP4 input subtitle tracks - Generalized websocket-based outputs to all support the same commands and run the same core logic - Added new "JSONLine" protocol that allows for generic direct line-by-line ingest of subtitles and/or JSON metadata tracks over a TCP socket or console standard input.
112 lines
3.8 KiB
C++
112 lines
3.8 KiB
C++
#include "output_jsonline.h"
|
|
#include <mist/defines.h>
|
|
#include <mist/http_parser.h>
|
|
#include <mist/url.h>
|
|
#include <mist/triggers.h>
|
|
#include <mist/stream.h>
|
|
|
|
namespace Mist{
|
|
OutJSONLine::OutJSONLine(Socket::Connection &conn) : Output(conn){
|
|
trkIdx = INVALID_TRACK_ID;
|
|
streamName = config->getString("streamname");
|
|
wantRequest = true;
|
|
parseData = false;
|
|
if (Triggers::shouldTrigger("PUSH_REWRITE")){
|
|
std::string payload = "jsonline://" + myConn.getBoundAddress() + ":" + config->getOption("port").asString() + "\n" + getConnectedHost() + "\n" + streamName;
|
|
std::string newStream = streamName;
|
|
Triggers::doTrigger("PUSH_REWRITE", payload, "", false, newStream);
|
|
if (!newStream.size()){
|
|
FAIL_MSG("Push from %s to URL %s rejected - PUSH_REWRITE trigger blanked the URL",
|
|
getConnectedHost().c_str(), reqUrl.c_str());
|
|
config->is_active = false;
|
|
return;
|
|
}else{
|
|
streamName = newStream;
|
|
Util::sanitizeName(streamName);
|
|
Util::setStreamName(streamName);
|
|
}
|
|
}
|
|
if (!allowPush("")){
|
|
FAIL_MSG("Pushing not allowed");
|
|
config->is_active = false;
|
|
return;
|
|
}
|
|
initialize();
|
|
trkIdx = meta.addTrack();
|
|
meta.setType(trkIdx, "meta");
|
|
meta.setCodec(trkIdx, config->getString("codec"));
|
|
meta.setID(trkIdx, 1);
|
|
offset = M.getBootMsOffset();
|
|
myConn.setBlocking(false);
|
|
INFO_MSG("%s track index is %zu", config->getString("codec").c_str(), trkIdx);
|
|
}
|
|
|
|
OutJSONLine::~OutJSONLine(){
|
|
if (trkIdx != INVALID_TRACK_ID && M){
|
|
meta.abandonTrack(trkIdx);
|
|
}
|
|
}
|
|
|
|
void OutJSONLine::init(Util::Config *cfg){
|
|
Output::init(cfg);
|
|
capa["name"] = "JSONLine";
|
|
capa["friendly"] = "JSON lines over raw TCP";
|
|
capa["desc"] = "Real time JSON line-by-line input over a raw TCP socket or standard input";
|
|
capa["deps"] = "";
|
|
capa["required"]["streamname"]["name"] = "Stream";
|
|
capa["required"]["streamname"]["help"] = "What streamname to serve. For multiple streams, add "
|
|
"this protocol multiple times using different ports.";
|
|
capa["required"]["streamname"]["type"] = "str";
|
|
capa["required"]["streamname"]["option"] = "--stream";
|
|
capa["required"]["streamname"]["short"] = "s";
|
|
|
|
cfg->addOption("codec",
|
|
JSON::fromString("{\"arg\":\"string\",\"default\":\"JSON\",\"short\":\"c\",\"long\":"
|
|
"\"codec\",\"help\":\"Codec to use for data ingest, JSON by default\"}"));
|
|
capa["optional"]["codec"]["name"] = "Codec";
|
|
capa["optional"]["codec"]["help"] = "What codec to ingest as";
|
|
capa["optional"]["codec"]["default"] = "JSON";
|
|
capa["optional"]["codec"]["type"] = "str";
|
|
capa["optional"]["codec"]["option"] = "--codec";
|
|
capa["optional"]["codec"]["short"] = "c";
|
|
|
|
capa["codecs"][0u][0u].append("JSON");
|
|
cfg->addConnectorOptions(3456, capa);
|
|
config = cfg;
|
|
}
|
|
|
|
void OutJSONLine::sendNext(){
|
|
}
|
|
|
|
bool OutJSONLine::listenMode(){return true;}
|
|
|
|
void OutJSONLine::requestHandler(){
|
|
if (myConn.spool()){
|
|
while (myConn.Received().size()){
|
|
dPtr.append(myConn.Received().get());
|
|
myConn.Received().get().clear();
|
|
if (dPtr.size() && dPtr[dPtr.size() - 1] == '\n'){
|
|
thisTime = Util::bootMS() - offset;
|
|
thisIdx = trkIdx;
|
|
thisPacket.genericFill(thisTime, 0, 1, dPtr, dPtr.size(), 0, true);
|
|
bufferLivePacket(thisPacket);
|
|
dPtr.truncate(0);
|
|
}
|
|
}
|
|
}else{
|
|
meta.setNowms(trkIdx, Util::bootMS() - offset);
|
|
Util::sleep(10);
|
|
}
|
|
}
|
|
|
|
std::string OutJSONLine::getStatsName(){
|
|
if (!parseData){
|
|
return "INPUT:" + capa["name"].asStringRef();
|
|
}else{
|
|
return Output::getStatsName();
|
|
}
|
|
}
|
|
|
|
bool OutJSONLine::isReadyForPlay(){return true;}
|
|
|
|
}// namespace Mist
|