TSSRT Support
This commit is contained in:
		
							parent
							
								
									974380ab30
								
							
						
					
					
						commit
						19199cbff8
					
				
					 17 changed files with 1471 additions and 15 deletions
				
			
		
							
								
								
									
										58
									
								
								src/output/mist_out_srt.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/output/mist_out_srt.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,58 @@ | |||
| #include OUTPUTTYPE | ||||
| #include <mist/config.h> | ||||
| #include <mist/defines.h> | ||||
| #include <mist/socket.h> | ||||
| #include <mist/socket_srt.h> | ||||
| #include <mist/util.h> | ||||
| 
 | ||||
| int spawnForked(Socket::SRTConnection &S){ | ||||
|   int fds[2]; | ||||
|   pipe(fds); | ||||
|   Socket::Connection Sconn(fds[0], fds[1]); | ||||
| 
 | ||||
|   mistOut tmp(Sconn, S.getSocket()); | ||||
|   return tmp.run(); | ||||
| } | ||||
| 
 | ||||
| void handleUSR1(int signum, siginfo_t *sigInfo, void *ignore){ | ||||
|   HIGH_MSG("USR1 received - triggering rolling restart"); | ||||
|   Util::Config::is_restarting = true; | ||||
|   Util::logExitReason("signal USR1"); | ||||
|   Util::Config::is_active = false; | ||||
| } | ||||
| 
 | ||||
| int main(int argc, char *argv[]){ | ||||
|   DTSC::trackValidMask = TRACK_VALID_EXT_HUMAN; | ||||
|   Util::redirectLogsIfNeeded(); | ||||
|   Util::Config conf(argv[0]); | ||||
|   mistOut::init(&conf); | ||||
|   if (conf.parseArgs(argc, argv)){ | ||||
|     if (conf.getBool("json")){ | ||||
|       mistOut::capa["version"] = PACKAGE_VERSION; | ||||
|       std::cout << mistOut::capa.toString() << std::endl; | ||||
|       return -1; | ||||
|     } | ||||
|     conf.activate(); | ||||
|     if (mistOut::listenMode()){ | ||||
|       { | ||||
|         struct sigaction new_action; | ||||
|         new_action.sa_sigaction = handleUSR1; | ||||
|         sigemptyset(&new_action.sa_mask); | ||||
|         new_action.sa_flags = 0; | ||||
|         sigaction(SIGUSR1, &new_action, NULL); | ||||
|       } | ||||
|       mistOut::listener(conf, spawnForked); | ||||
|       if (conf.is_restarting && Socket::checkTrueSocket(0)){ | ||||
|         INFO_MSG("Reloading input while re-using server socket"); | ||||
|         execvp(argv[0], argv); | ||||
|         FAIL_MSG("Error reloading: %s", strerror(errno)); | ||||
|       } | ||||
|     }else{ | ||||
|       Socket::Connection S(fileno(stdout), fileno(stdin)); | ||||
|       mistOut tmp(S, -1); | ||||
|       return tmp.run(); | ||||
|     } | ||||
|   } | ||||
|   INFO_MSG("Exit reason: %s", Util::exitReason); | ||||
|   return 0; | ||||
| } | ||||
							
								
								
									
										112
									
								
								src/output/output_tssrt.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								src/output/output_tssrt.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,112 @@ | |||
| #include "mist/socket_srt.h" | ||||
| #include "output_tssrt.h" | ||||
| #include <mist/defines.h> | ||||
| #include <mist/http_parser.h> | ||||
| #include <mist/url.h> | ||||
| 
 | ||||
| namespace Mist{ | ||||
|   OutTSSRT::OutTSSRT(Socket::Connection &conn, SRTSOCKET _srtSock) : TSOutput(conn){ | ||||
|     // NOTE: conn is useless for SRT, as it uses a different socket type.
 | ||||
|     sendRepeatingHeaders = 500; // PAT/PMT every 500ms (DVB spec)
 | ||||
|     streamName = config->getString("streamname"); | ||||
|     pushOut = false; | ||||
|     std::string tracks; | ||||
|     // Push output configuration
 | ||||
|     if (config->getString("target").size()){ | ||||
|       HTTP::URL target(config->getString("target")); | ||||
|       if (target.protocol != "srt"){ | ||||
|         FAIL_MSG("Target %s must begin with srt://, aborting", target.getUrl().c_str()); | ||||
|         onFail("Invalid srt target: doesn't start with srt://", true); | ||||
|         return; | ||||
|       } | ||||
|       if (!target.getPort()){ | ||||
|         FAIL_MSG("Target %s must contain a port, aborting", target.getUrl().c_str()); | ||||
|         onFail("Invalid srt target: missing port", true); | ||||
|         return; | ||||
|       } | ||||
|       pushOut = true; | ||||
|       if (targetParams.count("tracks")){tracks = targetParams["tracks"];} | ||||
|       size_t connectCnt = 0; | ||||
|       do{ | ||||
|         srtConn.connect(target.host, target.getPort(), "output"); | ||||
|         if (!srtConn){Util::sleep(1000);} | ||||
|         ++connectCnt; | ||||
|       }while (!srtConn && connectCnt < 10); | ||||
|       wantRequest = false; | ||||
|       parseData = true; | ||||
|     }else{ | ||||
|       // Pull output configuration, In this case we have an srt connection in the second constructor parameter.
 | ||||
|       srtConn = Socket::SRTConnection(_srtSock); | ||||
|       parseData = true; | ||||
|       wantRequest = false; | ||||
| 
 | ||||
|       // Handle override / append of streamname options
 | ||||
|       std::string sName = srtConn.getStreamName(); | ||||
|       if (sName != ""){ | ||||
|         streamName = sName; | ||||
|         HIGH_MSG("Requesting stream %s", streamName.c_str()); | ||||
|       } | ||||
|     } | ||||
|     initialize(); | ||||
|   } | ||||
| 
 | ||||
|   OutTSSRT::~OutTSSRT(){} | ||||
| 
 | ||||
|   void OutTSSRT::init(Util::Config *cfg){ | ||||
|     Output::init(cfg); | ||||
|     capa["name"] = "TSSRT"; | ||||
|     capa["friendly"] = "TS over SRT"; | ||||
|     capa["desc"] = "Real time streaming of TS data over SRT"; | ||||
|     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, " | ||||
|                                              "or use the streamid option on the srt connection"; | ||||
|     capa["required"]["streamname"]["type"] = "str"; | ||||
|     capa["required"]["streamname"]["option"] = "--stream"; | ||||
|     capa["required"]["streamname"]["short"] = "s"; | ||||
|     capa["codecs"][0u][0u].append("HEVC"); | ||||
|     capa["codecs"][0u][0u].append("H264"); | ||||
|     capa["codecs"][0u][0u].append("MPEG2"); | ||||
|     capa["codecs"][0u][1u].append("AAC"); | ||||
|     capa["codecs"][0u][1u].append("MP3"); | ||||
|     capa["codecs"][0u][1u].append("AC3"); | ||||
|     capa["codecs"][0u][1u].append("MP2"); | ||||
|     cfg->addConnectorOptions(8889, capa); | ||||
|     config = cfg; | ||||
|     capa["push_urls"].append("srt://*"); | ||||
| 
 | ||||
|     JSON::Value opt; | ||||
|     opt["arg"] = "string"; | ||||
|     opt["default"] = ""; | ||||
|     opt["arg_num"] = 1; | ||||
|     opt["help"] = "Target srt:// URL to push out towards."; | ||||
|     cfg->addOption("target", opt); | ||||
|   } | ||||
| 
 | ||||
|   // Buffer internally in the class, and send once we have over 1000 bytes of data.
 | ||||
|   void OutTSSRT::sendTS(const char *tsData, size_t len){ | ||||
|     if (packetBuffer.size() >= 1000){ | ||||
|       srtConn.SendNow(packetBuffer); | ||||
|       if (!srtConn){ | ||||
|         // Allow for proper disconnect
 | ||||
|         parseData = false; | ||||
|       } | ||||
|       packetBuffer.clear(); | ||||
|     } | ||||
|     packetBuffer.append(tsData, len); | ||||
|   } | ||||
| 
 | ||||
|   bool OutTSSRT::setAlternateConnectionStats(Comms::Statistics &statComm){ | ||||
|     statComm.setUp(srtConn.dataUp()); | ||||
|     statComm.setDown(srtConn.dataDown()); | ||||
|     statComm.setTime(Util::bootSecs() - srtConn.connTime()); | ||||
|     return true; | ||||
|   } | ||||
| 
 | ||||
|   void OutTSSRT::handleLossyStats(Comms::Statistics &statComm){ | ||||
|     statComm.setPacketCount(srtConn.packetCount()); | ||||
|     statComm.setPacketLostCount(srtConn.packetLostCount()); | ||||
|     statComm.setPacketRetransmitCount(srtConn.packetRetransmitCount()); | ||||
|   } | ||||
| }// namespace Mist
 | ||||
							
								
								
									
										33
									
								
								src/output/output_tssrt.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/output/output_tssrt.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,33 @@ | |||
| #include "output_ts_base.h" | ||||
| #include <mist/ts_stream.h> | ||||
| 
 | ||||
| #include <mist/socket_srt.h> | ||||
| 
 | ||||
| namespace Mist{ | ||||
|   class OutTSSRT : public TSOutput{ | ||||
|   public: | ||||
|     OutTSSRT(Socket::Connection &conn, SRTSOCKET _srtSock); | ||||
|     ~OutTSSRT(); | ||||
| 
 | ||||
|     static bool listenMode(){return !(config->getString("target").size());} | ||||
| 
 | ||||
|     static void init(Util::Config *cfg); | ||||
|     void sendTS(const char *tsData, size_t len = 188); | ||||
|     bool isReadyForPlay(){return true;} | ||||
| 
 | ||||
|   protected: | ||||
|     // Stats handling
 | ||||
|     virtual bool setAlternateConnectionStats(Comms::Statistics &statComm); | ||||
|     virtual void handleLossyStats(Comms::Statistics &statComm); | ||||
| 
 | ||||
|   private: | ||||
|     bool pushOut; | ||||
|     std::string packetBuffer; | ||||
|     Socket::UDPConnection pushSock; | ||||
|     TS::Stream tsIn; | ||||
| 
 | ||||
|     Socket::SRTConnection srtConn; | ||||
|   }; | ||||
| }// namespace Mist
 | ||||
| 
 | ||||
| typedef Mist::OutTSSRT mistOut; | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Phencys
						Phencys