From 4f7cfeed377b3c608fd8468a603361fbeeff94d7 Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 7 Apr 2014 10:15:44 +0800 Subject: [PATCH] change to 0.9.52, refine encoder and ffmpeg --- trunk/src/app/srs_app_encoder.cpp | 92 ++++++++++++++++++++++++++----- trunk/src/app/srs_app_encoder.hpp | 3 +- trunk/src/app/srs_app_ffmpeg.cpp | 67 ++++------------------ trunk/src/app/srs_app_ffmpeg.hpp | 15 ++--- trunk/src/core/srs_core.hpp | 2 +- 5 files changed, 101 insertions(+), 78 deletions(-) diff --git a/trunk/src/app/srs_app_encoder.cpp b/trunk/src/app/srs_app_encoder.cpp index c649bc926..8c06f9357 100644 --- a/trunk/src/app/srs_app_encoder.cpp +++ b/trunk/src/app/srs_app_encoder.cpp @@ -23,6 +23,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include +#include +using namespace std; + #include #include #include @@ -36,6 +39,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // when error, encoder sleep for a while and retry. #define SRS_ENCODER_SLEEP_US (int64_t)(3*1000*1000LL) +// for encoder to detect the dead loop +static std::vector _transcoded_url; + SrsEncoder::SrsEncoder() { pthread = new SrsThread(this, SRS_ENCODER_SLEEP_US); @@ -56,6 +62,7 @@ int SrsEncoder::on_publish(SrsRequest* req) ret = parse_scope_engines(req); // ignore the loop encoder + // if got a loop, donot transcode the whole stream. if (ret == ERROR_ENCODER_LOOP) { clear_engines(); ret = ERROR_SUCCESS; @@ -126,6 +133,15 @@ void SrsEncoder::clear_engines() for (it = ffmpegs.begin(); it != ffmpegs.end(); ++it) { SrsFFMPEG* ffmpeg = *it; + + std::string output = ffmpeg->output(); + + std::vector::iterator it; + it = std::find(_transcoded_url.begin(), _transcoded_url.end(), output); + if (it != _transcoded_url.end()) { + _transcoded_url.erase(it); + } + srs_freep(ffmpeg); } @@ -147,7 +163,7 @@ int SrsEncoder::parse_scope_engines(SrsRequest* req) // parse vhost scope engines std::string scope = ""; if ((conf = _srs_config->get_transcode(req->vhost, scope)) != NULL) { - if ((ret = parse_transcode(req, conf)) != ERROR_SUCCESS) { + if ((ret = parse_ffmpeg(req, conf)) != ERROR_SUCCESS) { srs_error("parse vhost scope=%s transcode engines failed. " "ret=%d", scope.c_str(), ret); return ret; @@ -156,7 +172,7 @@ int SrsEncoder::parse_scope_engines(SrsRequest* req) // parse app scope engines scope = req->app; if ((conf = _srs_config->get_transcode(req->vhost, scope)) != NULL) { - if ((ret = parse_transcode(req, conf)) != ERROR_SUCCESS) { + if ((ret = parse_ffmpeg(req, conf)) != ERROR_SUCCESS) { srs_error("parse app scope=%s transcode engines failed. " "ret=%d", scope.c_str(), ret); return ret; @@ -166,7 +182,7 @@ int SrsEncoder::parse_scope_engines(SrsRequest* req) scope += "/"; scope += req->stream; if ((conf = _srs_config->get_transcode(req->vhost, scope)) != NULL) { - if ((ret = parse_transcode(req, conf)) != ERROR_SUCCESS) { + if ((ret = parse_ffmpeg(req, conf)) != ERROR_SUCCESS) { srs_error("parse stream scope=%s transcode engines failed. " "ret=%d", scope.c_str(), ret); return ret; @@ -176,7 +192,7 @@ int SrsEncoder::parse_scope_engines(SrsRequest* req) return ret; } -int SrsEncoder::parse_transcode(SrsRequest* req, SrsConfDirective* conf) +int SrsEncoder::parse_ffmpeg(SrsRequest* req, SrsConfDirective* conf) { int ret = ERROR_SUCCESS; @@ -216,17 +232,9 @@ int SrsEncoder::parse_transcode(SrsRequest* req, SrsConfDirective* conf) } SrsFFMPEG* ffmpeg = new SrsFFMPEG(ffmpeg_bin); - - if ((ret = ffmpeg->initialize(req, engine)) != ERROR_SUCCESS) { + if ((ret = initialize_ffmpeg(ffmpeg, req, engine)) != ERROR_SUCCESS) { srs_freep(ffmpeg); - - // if got a loop, donot transcode the whole stream. - if (ret == ERROR_ENCODER_LOOP) { - break; - } - - srs_error("invalid transcode engine: %s %s", - conf->arg0().c_str(), engine->arg0().c_str()); + srs_error("invalid transcode engine: %s %s", conf->arg0().c_str(), engine->arg0().c_str()); return ret; } @@ -236,6 +244,62 @@ int SrsEncoder::parse_transcode(SrsRequest* req, SrsConfDirective* conf) return ret; } +int SrsEncoder::initialize_ffmpeg(SrsFFMPEG* ffmpeg, SrsRequest* req, SrsConfDirective* engine) +{ + int ret = ERROR_SUCCESS; + + std::string input; + // input stream, from local. + // ie. rtmp://127.0.0.1:1935/live/livestream + input = "rtmp://127.0.0.1:"; + input += req->port; + input += "/"; + input += req->app; + input += "?vhost="; + input += req->vhost; + input += "/"; + input += req->stream; + + std::string output = _srs_config->get_engine_output(engine); + // output stream, to other/self server + // ie. rtmp://127.0.0.1:1935/live/livestream_sd + output = srs_string_replace(output, "[vhost]", req->vhost); + output = srs_string_replace(output, "[port]", req->port); + output = srs_string_replace(output, "[app]", req->app); + output = srs_string_replace(output, "[stream]", req->stream); + output = srs_string_replace(output, "[engine]", engine->arg0()); + + std::string log_file; + // write ffmpeg info to log file. + log_file = _srs_config->get_ffmpeg_log_dir(); + log_file += "/"; + log_file += "encoder"; + log_file += "-"; + log_file += req->vhost; + log_file += "-"; + log_file += req->app; + log_file += "-"; + log_file += req->stream; + log_file += ".log"; + + // important: loop check, donot transcode again. + std::vector::iterator it; + it = std::find(_transcoded_url.begin(), _transcoded_url.end(), input); + if (it != _transcoded_url.end()) { + ret = ERROR_ENCODER_LOOP; + srs_info("detect a loop cycle, input=%s, output=%s, ignore it. ret=%d", + input.c_str(), output.c_str(), ret); + return ret; + } + _transcoded_url.push_back(output); + + if ((ret = ffmpeg->initialize(input, output, log_file, engine)) != ERROR_SUCCESS) { + return ret; + } + + return ret; +} + void SrsEncoder::encoder() { // reportable diff --git a/trunk/src/app/srs_app_encoder.hpp b/trunk/src/app/srs_app_encoder.hpp index 0be49b44b..bf7e79330 100644 --- a/trunk/src/app/srs_app_encoder.hpp +++ b/trunk/src/app/srs_app_encoder.hpp @@ -66,7 +66,8 @@ private: virtual void clear_engines(); virtual SrsFFMPEG* at(int index); virtual int parse_scope_engines(SrsRequest* req); - virtual int parse_transcode(SrsRequest* req, SrsConfDirective* conf); + virtual int parse_ffmpeg(SrsRequest* req, SrsConfDirective* conf); + virtual int initialize_ffmpeg(SrsFFMPEG* ffmpeg, SrsRequest* req, SrsConfDirective* engine); virtual void encoder(); }; diff --git a/trunk/src/app/srs_app_ffmpeg.cpp b/trunk/src/app/srs_app_ffmpeg.cpp index 6b5cbf974..5823a486e 100644 --- a/trunk/src/app/srs_app_ffmpeg.cpp +++ b/trunk/src/app/srs_app_ffmpeg.cpp @@ -30,7 +30,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include -#include +using namespace std; #include #include @@ -50,9 +50,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // for example, libaacplus, aac, fdkaac #define SRS_ENCODER_ACODEC "aac" -// for encoder to detect the dead loop -static std::vector _transcoded_url; - SrsFFMPEG::SrsFFMPEG(std::string ffmpeg_bin) { started = false; @@ -76,7 +73,12 @@ SrsFFMPEG::~SrsFFMPEG() stop(); } -int SrsFFMPEG::initialize(SrsRequest* req, SrsConfDirective* engine) +string SrsFFMPEG::output() +{ + return _output; +} + +int SrsFFMPEG::initialize(string in, string out, string log, SrsConfDirective* engine) { int ret = ERROR_SUCCESS; @@ -95,53 +97,14 @@ int SrsFFMPEG::initialize(SrsRequest* req, SrsConfDirective* engine) asample_rate = _srs_config->get_engine_asample_rate(engine); achannels = _srs_config->get_engine_achannels(engine); _srs_config->get_engine_aparams(engine, aparams); - output = _srs_config->get_engine_output(engine); // ensure the size is even. vwidth -= vwidth % 2; vheight -= vheight % 2; - - // input stream, from local. - // ie. rtmp://127.0.0.1:1935/live/livestream - input = "rtmp://127.0.0.1:"; - input += req->port; - input += "/"; - input += req->app; - input += "?vhost="; - input += req->vhost; - input += "/"; - input += req->stream; - // output stream, to other/self server - // ie. rtmp://127.0.0.1:1935/live/livestream_sd - output = srs_string_replace(output, "[vhost]", req->vhost); - output = srs_string_replace(output, "[port]", req->port); - output = srs_string_replace(output, "[app]", req->app); - output = srs_string_replace(output, "[stream]", req->stream); - output = srs_string_replace(output, "[engine]", engine->arg0()); - - // write ffmpeg info to log file. - log_file = _srs_config->get_ffmpeg_log_dir(); - log_file += "/"; - log_file += "encoder"; - log_file += "-"; - log_file += req->vhost; - log_file += "-"; - log_file += req->app; - log_file += "-"; - log_file += req->stream; - log_file += ".log"; - - // important: loop check, donot transcode again. - std::vector::iterator it; - it = std::find(_transcoded_url.begin(), _transcoded_url.end(), input); - if (it != _transcoded_url.end()) { - ret = ERROR_ENCODER_LOOP; - srs_info("detect a loop cycle, input=%s, output=%s, ignore it. ret=%d", - input.c_str(), output.c_str(), ret); - return ret; - } - _transcoded_url.push_back(output); + input = in; + _output = out; + log_file = log; if (vcodec == SRS_ENCODER_NO_VIDEO && acodec == SRS_ENCODER_NO_AUDIO) { ret = ERROR_ENCODER_VCODEC; @@ -219,7 +182,7 @@ int SrsFFMPEG::initialize(SrsRequest* req, SrsConfDirective* engine) return ret; } } - if (output.empty()) { + if (_output.empty()) { ret = ERROR_ENCODER_OUTPUT; srs_error("invalid empty output, ret=%d", ret); return ret; @@ -352,7 +315,7 @@ int SrsFFMPEG::start() params.push_back("flv"); params.push_back("-y"); - params.push_back(output); + params.push_back(_output); if (true) { int pparam_size = 8 * 1024; @@ -491,12 +454,6 @@ void SrsFFMPEG::stop() srs_trace("stop the encoder success. pid=%d", pid); pid = -1; } - - std::vector::iterator it; - it = std::find(_transcoded_url.begin(), _transcoded_url.end(), output); - if (it != _transcoded_url.end()) { - _transcoded_url.erase(it); - } } #endif diff --git a/trunk/src/app/srs_app_ffmpeg.hpp b/trunk/src/app/srs_app_ffmpeg.hpp index 437588ec1..9f5ce9498 100644 --- a/trunk/src/app/srs_app_ffmpeg.hpp +++ b/trunk/src/app/srs_app_ffmpeg.hpp @@ -35,7 +35,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include class SrsConfDirective; -class SrsRequest; class SrsPithyPrint; /** @@ -52,28 +51,30 @@ private: int log_fd; private: std::string ffmpeg; - std::vector vfilter; + std::vector vfilter; std::string vcodec; int vbitrate; - double vfps; + double vfps; int vwidth; int vheight; int vthreads; std::string vprofile; std::string vpreset; - std::vector vparams; + std::vector vparams; std::string acodec; int abitrate; int asample_rate; int achannels; - std::vector aparams; - std::string output; + std::vector aparams; + std::string _output; std::string input; public: SrsFFMPEG(std::string ffmpeg_bin); virtual ~SrsFFMPEG(); public: - virtual int initialize(SrsRequest* req, SrsConfDirective* engine); + virtual std::string output(); +public: + virtual int initialize(std::string in, std::string out, std::string log, SrsConfDirective* engine); virtual int start(); virtual int cycle(); virtual void stop(); diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index 73c80ef44..ffa750078 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // current release version #define VERSION_MAJOR "0" #define VERSION_MINOR "9" -#define VERSION_REVISION "51" +#define VERSION_REVISION "52" #define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION // server info. #define RTMP_SIG_SRS_KEY "srs"