diff --git a/README.md b/README.md index b68b1dbdb..3970859a0 100755 --- a/README.md +++ b/README.md @@ -117,7 +117,7 @@ usr sys idl wai hiq siq| read writ| recv send| in out | int csw * nginx v1.5.0: 139524 lines
### History -* v0.7, 2013-11-30, add transcoding params to config. +* v0.7, 2013-11-30, support live stream transcoding by ffmpeg. * v0.7, 2013-11-30, support --with/without -ffmpeg, build ffmpeg-2.1. * v0.7, 2013-11-30, add ffmpeg-2.1, x264-core138, lame-3.99.5, libaacplus-2.0.2. * v0.6, 2013-11-29, v0.6 released. 16094 lines. diff --git a/trunk/src/core/srs_core_config.cpp b/trunk/src/core/srs_core_config.cpp index 8ccd54e3c..055aac146 100644 --- a/trunk/src/core/srs_core_config.cpp +++ b/trunk/src/core/srs_core_config.cpp @@ -568,7 +568,7 @@ SrsConfDirective* SrsConfig::get_vhost_enabled(std::string vhost) return conf->get("enabled"); } -SrsConfDirective* SrsConfig::get_transcode(std::string vhost) +SrsConfDirective* SrsConfig::get_transcode(std::string vhost, std::string scope) { SrsConfDirective* conf = get_vhost(vhost); @@ -576,7 +576,16 @@ SrsConfDirective* SrsConfig::get_transcode(std::string vhost) return NULL; } - return conf->get("transcode"); + SrsConfDirective* transcode = conf->get("transcode"); + if (!transcode) { + return NULL; + } + + if (transcode->arg0() == scope) { + return transcode; + } + + return NULL; } SrsConfDirective* SrsConfig::get_gop_cache(std::string vhost) diff --git a/trunk/src/core/srs_core_config.hpp b/trunk/src/core/srs_core_config.hpp index 984e12742..ba62618d7 100644 --- a/trunk/src/core/srs_core_config.hpp +++ b/trunk/src/core/srs_core_config.hpp @@ -114,7 +114,7 @@ public: virtual int parse_options(int argc, char** argv); virtual SrsConfDirective* get_vhost(std::string vhost); virtual SrsConfDirective* get_vhost_enabled(std::string vhost); - virtual SrsConfDirective* get_transcode(std::string vhost); + virtual SrsConfDirective* get_transcode(std::string vhost, std::string scope); virtual SrsConfDirective* get_gop_cache(std::string vhost); virtual SrsConfDirective* get_forward(std::string vhost); virtual SrsConfDirective* get_hls(std::string vhost); diff --git a/trunk/src/core/srs_core_encoder.cpp b/trunk/src/core/srs_core_encoder.cpp index f31ceb99e..577b58f2a 100644 --- a/trunk/src/core/srs_core_encoder.cpp +++ b/trunk/src/core/srs_core_encoder.cpp @@ -25,22 +25,89 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include +#include + +#define SRS_ENCODER_SLEEP_MS 2000 SrsEncoder::SrsEncoder() { + tid = NULL; + loop = false; } SrsEncoder::~SrsEncoder() { + on_unpublish(); } -int SrsEncoder::on_publish(std::string vhost, std::string app, std::string stream) +int SrsEncoder::on_publish(std::string _vhost, std::string _app, std::string _stream) { int ret = ERROR_SUCCESS; + + vhost = _vhost; + app = _app; + stream = _stream; + + srs_assert(!tid); + if((tid = st_thread_create(encoder_thread, this, 1, 0)) == NULL){ + ret = ERROR_ST_CREATE_FORWARD_THREAD; + srs_error("st_thread_create failed. ret=%d", ret); + return ret; + } + return ret; } void SrsEncoder::on_unpublish() { + if (tid) { + loop = false; + st_thread_interrupt(tid); + st_thread_join(tid, NULL); + tid = NULL; + } +} + +int SrsEncoder::cycle() +{ + int ret = ERROR_SUCCESS; + return ret; +} + +void SrsEncoder::encoder_cycle() +{ + int ret = ERROR_SUCCESS; + + log_context->generate_id(); + srs_trace("encoder cycle start"); + + while (loop) { + if ((ret = cycle()) != ERROR_SUCCESS) { + srs_warn("encoder cycle failed, ignored and retry, ret=%d", ret); + } else { + srs_info("encoder cycle success, retry"); + } + + if (!loop) { + break; + } + + st_usleep(SRS_ENCODER_SLEEP_MS * 1000); + } + + // TODO: kill ffmpeg when finished and it alive + + srs_trace("encoder cycle finished"); +} + +void* SrsEncoder::encoder_thread(void* arg) +{ + SrsEncoder* obj = (SrsEncoder*)arg; + srs_assert(obj != NULL); + + obj->loop = true; + obj->encoder_cycle(); + + return NULL; } diff --git a/trunk/src/core/srs_core_encoder.hpp b/trunk/src/core/srs_core_encoder.hpp index 3ea39ee08..d4932d442 100644 --- a/trunk/src/core/srs_core_encoder.hpp +++ b/trunk/src/core/srs_core_encoder.hpp @@ -31,14 +31,27 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include +#include + class SrsEncoder { +private: + std::string vhost; + std::string app; + std::string stream; +private: + st_thread_t tid; + bool loop; public: SrsEncoder(); virtual ~SrsEncoder(); public: virtual int on_publish(std::string vhost, std::string app, std::string stream); virtual void on_unpublish(); +private: + virtual int cycle(); + virtual void encoder_cycle(); + static void* encoder_thread(void* arg); }; #endif diff --git a/trunk/src/core/srs_core_forward.cpp b/trunk/src/core/srs_core_forward.cpp index 26bdbec13..967ba807b 100644 --- a/trunk/src/core/srs_core_forward.cpp +++ b/trunk/src/core/srs_core_forward.cpp @@ -43,10 +43,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SrsForwarder::SrsForwarder() { client = NULL; - tid = NULL; stfd = NULL; - loop = false; stream_id = 0; + + tid = NULL; + loop = false; } SrsForwarder::~SrsForwarder() @@ -221,7 +222,7 @@ std::string SrsForwarder::parse_server(std::string host) return ipv4; } -int SrsForwarder::forward_cycle_imp() +int SrsForwarder::cycle() { int ret = ERROR_SUCCESS; @@ -316,7 +317,7 @@ void SrsForwarder::forward_cycle() srs_trace("forward cycle start"); while (loop) { - if ((ret = forward_cycle_imp()) != ERROR_SUCCESS) { + if ((ret = cycle()) != ERROR_SUCCESS) { srs_warn("forward cycle failed, ignored and retry, ret=%d", ret); } else { srs_info("forward cycle success, retry"); diff --git a/trunk/src/core/srs_core_forward.hpp b/trunk/src/core/srs_core_forward.hpp index dde732810..3bb8d4639 100644 --- a/trunk/src/core/srs_core_forward.hpp +++ b/trunk/src/core/srs_core_forward.hpp @@ -71,7 +71,7 @@ private: virtual int connect_server(); std::string parse_server(std::string host); private: - virtual int forward_cycle_imp(); + virtual int cycle(); virtual int forward(); virtual void forward_cycle(); static void* forward_thread(void* arg);