Fixed .flv recording
Added .ts recording Added .mp3 recording Added support for stdout output in FLV, MP3 and HTTPTS outputs
This commit is contained in:
parent
263dee7b25
commit
8ddfb000df
6 changed files with 130 additions and 35 deletions
|
@ -5,7 +5,28 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
namespace Mist {
|
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() {}
|
OutHTTPTS::~OutHTTPTS() {}
|
||||||
|
|
||||||
|
@ -24,7 +45,18 @@ namespace Mist {
|
||||||
capa["methods"][0u]["handler"] = "http";
|
capa["methods"][0u]["handler"] = "http";
|
||||||
capa["methods"][0u]["type"] = "html5/video/mp2t";
|
capa["methods"][0u]["type"] = "html5/video/mp2t";
|
||||||
capa["methods"][0u]["priority"] = 1ll;
|
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(){
|
void OutHTTPTS::onHTTP(){
|
||||||
|
@ -44,9 +76,11 @@ namespace Mist {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OutHTTPTS::sendTS(const char * tsData, unsigned int len){
|
void OutHTTPTS::sendTS(const char * tsData, unsigned int len){
|
||||||
//if (!recording()){
|
if (!isRecording()){
|
||||||
H.Chunkify(tsData, len, myConn);
|
H.Chunkify(tsData, len, myConn);
|
||||||
//}
|
}else{
|
||||||
|
myConn.SendNow(tsData, len);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,13 +9,8 @@ namespace Mist {
|
||||||
static void init(Util::Config * cfg);
|
static void init(Util::Config * cfg);
|
||||||
void onHTTP();
|
void onHTTP();
|
||||||
void sendTS(const char * tsData, unsigned int len=188);
|
void sendTS(const char * tsData, unsigned int len=188);
|
||||||
protected:
|
private:
|
||||||
int keysToSend;
|
bool isRecording();
|
||||||
long long int playUntil;
|
|
||||||
long long unsigned int lastVid;
|
|
||||||
long long unsigned int until;
|
|
||||||
unsigned int vidTrack;
|
|
||||||
unsigned int audTrack;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,28 @@
|
||||||
#include "output_progressive_flv.h"
|
#include "output_progressive_flv.h"
|
||||||
|
|
||||||
namespace Mist {
|
namespace Mist {
|
||||||
OutProgressiveFLV::OutProgressiveFLV(Socket::Connection & conn) : HTTPOutput(conn){}
|
OutProgressiveFLV::OutProgressiveFLV(Socket::Connection & conn) : HTTPOutput(conn){
|
||||||
OutProgressiveFLV::~OutProgressiveFLV() {}
|
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){
|
void OutProgressiveFLV::init(Util::Config * cfg){
|
||||||
HTTPOutput::init(cfg);
|
HTTPOutput::init(cfg);
|
||||||
|
@ -29,7 +49,18 @@ namespace Mist {
|
||||||
capa["methods"][0u]["type"] = "flash/7";
|
capa["methods"][0u]["type"] = "flash/7";
|
||||||
capa["methods"][0u]["priority"] = 5ll;
|
capa["methods"][0u]["priority"] = 5ll;
|
||||||
capa["methods"][0u]["player_url"] = "/oldflashplayer.swf";
|
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(){
|
void OutProgressiveFLV::sendNext(){
|
||||||
|
@ -38,13 +69,14 @@ namespace Mist {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OutProgressiveFLV::sendHeader(){
|
void OutProgressiveFLV::sendHeader(){
|
||||||
|
if (!isRecording()){
|
||||||
|
H.Clean();
|
||||||
H.Clean();
|
H.SetHeader("Content-Type", "video/x-flv");
|
||||||
H.SetHeader("Content-Type", "video/x-flv");
|
H.protocol = "HTTP/1.0";
|
||||||
H.protocol = "HTTP/1.0";
|
H.setCORSHeaders();
|
||||||
H.setCORSHeaders();
|
H.SendResponse("200", "OK", myConn);
|
||||||
sendResponse();
|
}
|
||||||
|
|
||||||
myConn.SendNow(FLV::Header, 13);
|
myConn.SendNow(FLV::Header, 13);
|
||||||
tag.DTSCMetaInit(myMeta, selectedTracks);
|
tag.DTSCMetaInit(myMeta, selectedTracks);
|
||||||
myConn.SendNow(tag.data, tag.len);
|
myConn.SendNow(tag.data, tag.len);
|
||||||
|
|
|
@ -5,13 +5,13 @@ namespace Mist {
|
||||||
class OutProgressiveFLV : public HTTPOutput {
|
class OutProgressiveFLV : public HTTPOutput {
|
||||||
public:
|
public:
|
||||||
OutProgressiveFLV(Socket::Connection & conn);
|
OutProgressiveFLV(Socket::Connection & conn);
|
||||||
~OutProgressiveFLV();
|
|
||||||
static void init(Util::Config * cfg);
|
static void init(Util::Config * cfg);
|
||||||
void onHTTP();
|
void onHTTP();
|
||||||
void sendNext();
|
void sendNext();
|
||||||
void sendHeader();
|
void sendHeader();
|
||||||
private:
|
private:
|
||||||
FLV::Tag tag;
|
FLV::Tag tag;
|
||||||
|
bool isRecording();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,29 @@
|
||||||
#include "output_progressive_mp3.h"
|
#include "output_progressive_mp3.h"
|
||||||
|
|
||||||
namespace Mist {
|
namespace Mist {
|
||||||
OutProgressiveMP3::OutProgressiveMP3(Socket::Connection & conn) : HTTPOutput(conn){}
|
OutProgressiveMP3::OutProgressiveMP3(Socket::Connection & conn) : HTTPOutput(conn){
|
||||||
OutProgressiveMP3::~OutProgressiveMP3(){}
|
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){
|
void OutProgressiveMP3::init(Util::Config * cfg){
|
||||||
HTTPOutput::init(cfg);
|
HTTPOutput::init(cfg);
|
||||||
capa["name"] = "MP3";
|
capa["name"] = "MP3";
|
||||||
|
@ -14,6 +34,17 @@ namespace Mist {
|
||||||
capa["methods"][0u]["handler"] = "http";
|
capa["methods"][0u]["handler"] = "http";
|
||||||
capa["methods"][0u]["type"] = "html5/audio/mp3";
|
capa["methods"][0u]["type"] = "html5/audio/mp3";
|
||||||
capa["methods"][0u]["priority"] = 8ll;
|
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(){
|
void OutProgressiveMP3::sendNext(){
|
||||||
|
@ -24,16 +55,18 @@ namespace Mist {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OutProgressiveMP3::sendHeader(){
|
void OutProgressiveMP3::sendHeader(){
|
||||||
std::string method = H.method;
|
if (!isRecording()){
|
||||||
H.Clean();
|
std::string method = H.method;
|
||||||
H.SetHeader("Content-Type", "audio/mpeg");
|
H.Clean();
|
||||||
H.protocol = "HTTP/1.0";
|
H.SetHeader("Content-Type", "audio/mpeg");
|
||||||
H.setCORSHeaders();
|
H.protocol = "HTTP/1.0";
|
||||||
if(method == "OPTIONS" || method == "HEAD"){
|
H.setCORSHeaders();
|
||||||
|
if(method == "OPTIONS" || method == "HEAD"){
|
||||||
|
H.SendResponse("200", "OK", myConn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
H.SendResponse("200", "OK", myConn);
|
H.SendResponse("200", "OK", myConn);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
H.SendResponse("200", "OK", myConn);
|
|
||||||
sentHeader = true;
|
sentHeader = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,12 @@ namespace Mist {
|
||||||
class OutProgressiveMP3 : public HTTPOutput {
|
class OutProgressiveMP3 : public HTTPOutput {
|
||||||
public:
|
public:
|
||||||
OutProgressiveMP3(Socket::Connection & conn);
|
OutProgressiveMP3(Socket::Connection & conn);
|
||||||
~OutProgressiveMP3();
|
|
||||||
static void init(Util::Config * cfg);
|
static void init(Util::Config * cfg);
|
||||||
void onHTTP();
|
void onHTTP();
|
||||||
void sendNext();
|
void sendNext();
|
||||||
void sendHeader();
|
void sendHeader();
|
||||||
|
private:
|
||||||
|
bool isRecording();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue