From 8ddfb000df02328db79c6d8e05d149f2a9092db4 Mon Sep 17 00:00:00 2001 From: Thulinma Date: Tue, 10 May 2016 00:19:15 +0200 Subject: [PATCH] Fixed .flv recording Added .ts recording Added .mp3 recording Added support for stdout output in FLV, MP3 and HTTPTS outputs --- src/output/output_httpts.cpp | 44 ++++++++++++++++++--- src/output/output_httpts.h | 9 +---- src/output/output_progressive_flv.cpp | 52 ++++++++++++++++++++----- src/output/output_progressive_flv.h | 2 +- src/output/output_progressive_mp3.cpp | 55 +++++++++++++++++++++------ src/output/output_progressive_mp3.h | 3 +- 6 files changed, 130 insertions(+), 35 deletions(-) diff --git a/src/output/output_httpts.cpp b/src/output/output_httpts.cpp index 12e96024..d5735c7f 100644 --- a/src/output/output_httpts.cpp +++ b/src/output/output_httpts.cpp @@ -5,7 +5,28 @@ #include namespace Mist { - OutHTTPTS::OutHTTPTS(Socket::Connection & conn) : TSOutput(conn) {} + OutHTTPTS::OutHTTPTS(Socket::Connection & conn) : TSOutput(conn){ + if (config->getString("target").size()){ + if (!streamName.size()){ + WARN_MSG("Recording unconnected TS output to file! Cancelled."); + conn.close(); + return; + } + if (config->getString("target") == "-"){ + parseData = true; + wantRequest = false; + INFO_MSG("Outputting %s to stdout in TS format", streamName.c_str()); + return; + } + if (connectToFile(config->getString("target"))){ + parseData = true; + wantRequest = false; + INFO_MSG("Recording %s to %s in TS format", streamName.c_str(), config->getString("target").c_str()); + }else{ + conn.close(); + } + } + } OutHTTPTS::~OutHTTPTS() {} @@ -24,7 +45,18 @@ namespace Mist { capa["methods"][0u]["handler"] = "http"; capa["methods"][0u]["type"] = "html5/video/mp2t"; capa["methods"][0u]["priority"] = 1ll; - capa["canRecord"].append("ts"); + capa["push_urls"].append("/*.ts"); + + JSON::Value opt; + opt["arg"] = "string"; + opt["default"] = ""; + opt["arg_num"] = 1ll; + opt["help"] = "Target filename to store TS file as, or - for stdout."; + cfg->addOption("target", opt); + } + + bool OutHTTPTS::isRecording(){ + return config->getString("target").size(); } void OutHTTPTS::onHTTP(){ @@ -44,9 +76,11 @@ namespace Mist { } void OutHTTPTS::sendTS(const char * tsData, unsigned int len){ - //if (!recording()){ + if (!isRecording()){ H.Chunkify(tsData, len, myConn); - //} + }else{ + myConn.SendNow(tsData, len); + } } - } + diff --git a/src/output/output_httpts.h b/src/output/output_httpts.h index 84ebb85f..69e8390c 100644 --- a/src/output/output_httpts.h +++ b/src/output/output_httpts.h @@ -9,13 +9,8 @@ namespace Mist { static void init(Util::Config * cfg); void onHTTP(); void sendTS(const char * tsData, unsigned int len=188); - protected: - int keysToSend; - long long int playUntil; - long long unsigned int lastVid; - long long unsigned int until; - unsigned int vidTrack; - unsigned int audTrack; + private: + bool isRecording(); }; } diff --git a/src/output/output_progressive_flv.cpp b/src/output/output_progressive_flv.cpp index 0e017d33..37e2a0b3 100644 --- a/src/output/output_progressive_flv.cpp +++ b/src/output/output_progressive_flv.cpp @@ -1,8 +1,28 @@ #include "output_progressive_flv.h" namespace Mist { - OutProgressiveFLV::OutProgressiveFLV(Socket::Connection & conn) : HTTPOutput(conn){} - OutProgressiveFLV::~OutProgressiveFLV() {} + OutProgressiveFLV::OutProgressiveFLV(Socket::Connection & conn) : HTTPOutput(conn){ + if (config->getString("target").size()){ + if (!streamName.size()){ + WARN_MSG("Recording unconnected FLV output to file! Cancelled."); + conn.close(); + return; + } + if (config->getString("target") == "-"){ + parseData = true; + wantRequest = false; + INFO_MSG("Outputting %s to stdout in FLV format", streamName.c_str()); + return; + } + if (connectToFile(config->getString("target"))){ + parseData = true; + wantRequest = false; + INFO_MSG("Recording %s to %s in FLV format", streamName.c_str(), config->getString("target").c_str()); + }else{ + conn.close(); + } + } + } void OutProgressiveFLV::init(Util::Config * cfg){ HTTPOutput::init(cfg); @@ -29,7 +49,18 @@ namespace Mist { capa["methods"][0u]["type"] = "flash/7"; capa["methods"][0u]["priority"] = 5ll; capa["methods"][0u]["player_url"] = "/oldflashplayer.swf"; - capa["canRecord"].append("flv"); + capa["push_urls"].append("/*.flv"); + + JSON::Value opt; + opt["arg"] = "string"; + opt["default"] = ""; + opt["arg_num"] = 1ll; + opt["help"] = "Target filename to store FLV file as, or - for stdout."; + cfg->addOption("target", opt); + } + + bool OutProgressiveFLV::isRecording(){ + return config->getString("target").size(); } void OutProgressiveFLV::sendNext(){ @@ -38,13 +69,14 @@ namespace Mist { } void OutProgressiveFLV::sendHeader(){ - - - H.Clean(); - H.SetHeader("Content-Type", "video/x-flv"); - H.protocol = "HTTP/1.0"; - H.setCORSHeaders(); - sendResponse(); + if (!isRecording()){ + H.Clean(); + H.SetHeader("Content-Type", "video/x-flv"); + H.protocol = "HTTP/1.0"; + H.setCORSHeaders(); + H.SendResponse("200", "OK", myConn); + } + myConn.SendNow(FLV::Header, 13); tag.DTSCMetaInit(myMeta, selectedTracks); myConn.SendNow(tag.data, tag.len); diff --git a/src/output/output_progressive_flv.h b/src/output/output_progressive_flv.h index 12cdee95..62af98fe 100644 --- a/src/output/output_progressive_flv.h +++ b/src/output/output_progressive_flv.h @@ -5,13 +5,13 @@ namespace Mist { class OutProgressiveFLV : public HTTPOutput { public: OutProgressiveFLV(Socket::Connection & conn); - ~OutProgressiveFLV(); static void init(Util::Config * cfg); void onHTTP(); void sendNext(); void sendHeader(); private: FLV::Tag tag; + bool isRecording(); }; } diff --git a/src/output/output_progressive_mp3.cpp b/src/output/output_progressive_mp3.cpp index 571f16bb..1df75204 100644 --- a/src/output/output_progressive_mp3.cpp +++ b/src/output/output_progressive_mp3.cpp @@ -1,9 +1,29 @@ #include "output_progressive_mp3.h" namespace Mist { - OutProgressiveMP3::OutProgressiveMP3(Socket::Connection & conn) : HTTPOutput(conn){} - OutProgressiveMP3::~OutProgressiveMP3(){} - + OutProgressiveMP3::OutProgressiveMP3(Socket::Connection & conn) : HTTPOutput(conn){ + if (config->getString("target").size()){ + if (!streamName.size()){ + WARN_MSG("Recording unconnected MP3 output to file! Cancelled."); + conn.close(); + return; + } + if (config->getString("target") == "-"){ + parseData = true; + wantRequest = false; + INFO_MSG("Outputting %s to stdout in MP3 format", streamName.c_str()); + return; + } + if (connectToFile(config->getString("target"))){ + parseData = true; + wantRequest = false; + INFO_MSG("Recording %s to %s in MP3 format", streamName.c_str(), config->getString("target").c_str()); + }else{ + conn.close(); + } + } + } + void OutProgressiveMP3::init(Util::Config * cfg){ HTTPOutput::init(cfg); capa["name"] = "MP3"; @@ -14,6 +34,17 @@ namespace Mist { capa["methods"][0u]["handler"] = "http"; capa["methods"][0u]["type"] = "html5/audio/mp3"; capa["methods"][0u]["priority"] = 8ll; + + JSON::Value opt; + opt["arg"] = "string"; + opt["default"] = ""; + opt["arg_num"] = 1ll; + opt["help"] = "Target filename to store MP3 file as, or - for stdout."; + cfg->addOption("target", opt); + } + + bool OutProgressiveMP3::isRecording(){ + return config->getString("target").size(); } void OutProgressiveMP3::sendNext(){ @@ -24,16 +55,18 @@ namespace Mist { } void OutProgressiveMP3::sendHeader(){ - std::string method = H.method; - H.Clean(); - H.SetHeader("Content-Type", "audio/mpeg"); - H.protocol = "HTTP/1.0"; - H.setCORSHeaders(); - if(method == "OPTIONS" || method == "HEAD"){ + if (!isRecording()){ + std::string method = H.method; + H.Clean(); + H.SetHeader("Content-Type", "audio/mpeg"); + H.protocol = "HTTP/1.0"; + H.setCORSHeaders(); + if(method == "OPTIONS" || method == "HEAD"){ + H.SendResponse("200", "OK", myConn); + return; + } H.SendResponse("200", "OK", myConn); - return; } - H.SendResponse("200", "OK", myConn); sentHeader = true; } diff --git a/src/output/output_progressive_mp3.h b/src/output/output_progressive_mp3.h index 9afe9ec6..1a1819aa 100644 --- a/src/output/output_progressive_mp3.h +++ b/src/output/output_progressive_mp3.h @@ -5,11 +5,12 @@ namespace Mist { class OutProgressiveMP3 : public HTTPOutput { public: OutProgressiveMP3(Socket::Connection & conn); - ~OutProgressiveMP3(); static void init(Util::Config * cfg); void onHTTP(); void sendNext(); void sendHeader(); + private: + bool isRecording(); }; }