diff --git a/trunk/conf/srs.conf b/trunk/conf/srs.conf index d4c3bf497..0748b3cca 100755 --- a/trunk/conf/srs.conf +++ b/trunk/conf/srs.conf @@ -6,6 +6,10 @@ listen 1935; # performance about 10%. # if not specified, set to 4096. chunk_size 65000; +# the logs dir. +# if enabled ffmpeg, each stracoding stream will create a log file. +# default: ./objs/logs +log_dir ./objs/logs; # vhost list, the __defaultVhost__ is the default vhost # for which cannot identify the required vhost. # for default demo. @@ -76,10 +80,10 @@ vhost dev { hls_path ./objs/nginx/html; hls_fragment 5; hls_window 30; - #forward 127.0.0.1:19350; + forward 127.0.0.1:19350; #forward 127.0.0.1:1936; transcode { - enabled off; + enabled on; ffmpeg ./objs/ffmpeg/bin/ffmpeg; engine dev { enabled on; @@ -511,6 +515,12 @@ pithy_print { # shared print interval for all forwarders, in milliseconds. # if not specified, set to 2000. forwarder 3000; + # shared print interval for all encoders, in milliseconds. + # if not specified, set to 2000. + encoder 3000; + # shared print interval for all hls, in milliseconds. + # if not specified, set to 2000. + hls 3000; } diff --git a/trunk/configure b/trunk/configure index f0a1c6aa0..a8aec63c9 100755 --- a/trunk/configure +++ b/trunk/configure @@ -144,6 +144,9 @@ else echo -e "${YELLOW}warning: without live stream transcoding over FFMPEG support${BLACK}" fi +# mkdir dirs +mkdir -p ${SRS_OBJS}/logs + # next step. echo "" echo "you can:" diff --git a/trunk/src/core/srs_core_config.cpp b/trunk/src/core/srs_core_config.cpp index 60c64c572..c5aeaa84d 100644 --- a/trunk/src/core/srs_core_config.cpp +++ b/trunk/src/core/srs_core_config.cpp @@ -904,6 +904,17 @@ std::string SrsConfig::get_engine_output(SrsConfDirective* engine) return conf->arg0(); } +std::string SrsConfig::get_log_dir() +{ + srs_assert(root); + + SrsConfDirective* conf = root->get("log_dir"); + if (!conf || conf->arg0().empty()) { + return "./objs/logs"; + } + + return conf->arg0(); +} SrsConfDirective* SrsConfig::get_gop_cache(std::string vhost) { @@ -1049,6 +1060,26 @@ SrsConfDirective* SrsConfig::get_pithy_print_forwarder() return pithy->get("forwarder"); } +SrsConfDirective* SrsConfig::get_pithy_print_hls() +{ + SrsConfDirective* pithy = root->get("pithy_print"); + if (!pithy) { + return NULL; + } + + return pithy->get("hls"); +} + +SrsConfDirective* SrsConfig::get_pithy_print_encoder() +{ + SrsConfDirective* pithy = root->get("encoder"); + if (!pithy) { + return NULL; + } + + return pithy->get("forwarder"); +} + SrsConfDirective* SrsConfig::get_pithy_print_play() { SrsConfDirective* pithy = root->get("pithy_print"); diff --git a/trunk/src/core/srs_core_config.hpp b/trunk/src/core/srs_core_config.hpp index 979578934..612876819 100644 --- a/trunk/src/core/srs_core_config.hpp +++ b/trunk/src/core/srs_core_config.hpp @@ -140,6 +140,7 @@ public: virtual int get_engine_achannels(SrsConfDirective* engine); virtual void get_engine_aparams(SrsConfDirective* engine, std::vector& aparams); virtual std::string get_engine_output(SrsConfDirective* engine); + virtual std::string get_log_dir(); virtual SrsConfDirective* get_gop_cache(std::string vhost); virtual SrsConfDirective* get_forward(std::string vhost); virtual SrsConfDirective* get_hls(std::string vhost); @@ -154,6 +155,8 @@ public: virtual SrsConfDirective* get_chunk_size(); virtual SrsConfDirective* get_pithy_print_publish(); virtual SrsConfDirective* get_pithy_print_forwarder(); + virtual SrsConfDirective* get_pithy_print_encoder(); + virtual SrsConfDirective* get_pithy_print_hls(); virtual SrsConfDirective* get_pithy_print_play(); private: virtual int parse_file(const char* filename); diff --git a/trunk/src/core/srs_core_encoder.cpp b/trunk/src/core/srs_core_encoder.cpp index 5ad23e83c..be0e5cb77 100644 --- a/trunk/src/core/srs_core_encoder.cpp +++ b/trunk/src/core/srs_core_encoder.cpp @@ -26,6 +26,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include #include +#include #include @@ -33,6 +34,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include #include +#include #ifdef SRS_FFMPEG @@ -58,6 +60,8 @@ SrsFFMPEG::SrsFFMPEG(std::string ffmpeg_bin) abitrate = 0; asample_rate = 0; achannels = 0; + + log_fd = -1; } SrsFFMPEG::~SrsFFMPEG() @@ -108,6 +112,18 @@ int SrsFFMPEG::initialize(SrsRequest* req, SrsConfDirective* engine) output = srs_replace(output, "[app]", req->app); output = srs_replace(output, "[stream]", req->stream); output = srs_replace(output, "[engine]", engine->arg0()); + + // write ffmpeg info to log file. + log_file = config->get_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; @@ -316,7 +332,8 @@ int SrsFFMPEG::start() snprintf(p, last - p, "%s ", ffp.c_str()); p += ffp.length() + 1; } - srs_trace("start transcoder: %s", pparam); + srs_trace("start transcoder, log: %s, params: %s", + log_file.c_str(), pparam); srs_freepa(pparam); } @@ -329,6 +346,30 @@ int SrsFFMPEG::start() // child process: ffmpeg encoder engine. if (pid == 0) { + // redirect logs to file. + int flags = O_CREAT|O_WRONLY|O_APPEND; + mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH; + if ((log_fd = ::open(log_file.c_str(), flags, mode)) < 0) { + ret = ERROR_ENCODER_OPEN; + srs_error("open encoder file %s failed. ret=%d", log_file.c_str(), ret); + return ret; + } + if (dup2(log_fd, STDOUT_FILENO) < 0) { + ret = ERROR_ENCODER_DUP2; + srs_error("dup2 encoder file failed. ret=%d", ret); + return ret; + } + if (dup2(log_fd, STDERR_FILENO) < 0) { + ret = ERROR_ENCODER_DUP2; + srs_error("dup2 encoder file failed. ret=%d", ret); + return ret; + } + // close other fds + // TODO: do in right way. + for (int i = 3; i < 1024; i++) { + ::close(i); + } + // memory leak in child process, it's ok. char** charpv_params = new char*[params.size() + 1]; for (int i = 0; i < (int)params.size(); i++) { @@ -389,6 +430,11 @@ int SrsFFMPEG::cycle() void SrsFFMPEG::stop() { + if (log_fd > 0) { + ::close(log_fd); + log_fd = -1; + } + if (!started) { return; } @@ -598,6 +644,8 @@ void SrsEncoder::encoder_cycle() log_context->generate_id(); srs_trace("encoder cycle start"); + SrsPithyPrint pithy_print(SRS_STAGE_ENCODER); + while (loop) { if ((ret = cycle()) != ERROR_SUCCESS) { srs_warn("encoder cycle failed, ignored and retry, ret=%d", ret); @@ -608,6 +656,9 @@ void SrsEncoder::encoder_cycle() if (!loop) { break; } + + encoder(&pithy_print); + pithy_print.elapse(SRS_ENCODER_SLEEP_MS); st_usleep(SRS_ENCODER_SLEEP_MS * 1000); } @@ -622,6 +673,15 @@ void SrsEncoder::encoder_cycle() srs_trace("encoder cycle finished"); } +void SrsEncoder::encoder(SrsPithyPrint* pithy_print) +{ + // reportable + if (pithy_print->can_print()) { + srs_trace("-> time=%"PRId64", encoders=%d", + pithy_print->get_age(), (int)ffmpegs.size()); + } +} + void* SrsEncoder::encoder_thread(void* arg) { SrsEncoder* obj = (SrsEncoder*)arg; diff --git a/trunk/src/core/srs_core_encoder.hpp b/trunk/src/core/srs_core_encoder.hpp index 73c345ae1..6149ce4f3 100644 --- a/trunk/src/core/srs_core_encoder.hpp +++ b/trunk/src/core/srs_core_encoder.hpp @@ -36,6 +36,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. class SrsConfDirective; class SrsRequest; +class SrsPithyPrint; #ifdef SRS_FFMPEG @@ -48,6 +49,9 @@ class SrsFFMPEG private: bool started; pid_t pid; +private: + std::string log_file; + int log_fd; private: std::string ffmpeg; std::vector vfilter; @@ -101,6 +105,7 @@ private: virtual int parse_transcode(SrsRequest* req, SrsConfDirective* conf); virtual int cycle(); virtual void encoder_cycle(); + virtual void encoder(SrsPithyPrint* pithy_print); static void* encoder_thread(void* arg); }; diff --git a/trunk/src/core/srs_core_error.hpp b/trunk/src/core/srs_core_error.hpp index ddfeb053a..291801208 100644 --- a/trunk/src/core/srs_core_error.hpp +++ b/trunk/src/core/srs_core_error.hpp @@ -139,5 +139,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define ERROR_ENCODER_VBITRATE 712 #define ERROR_ENCODER_FORK 713 #define ERROR_ENCODER_LOOP 714 +#define ERROR_ENCODER_OPEN 715 +#define ERROR_ENCODER_DUP2 716 #endif \ No newline at end of file diff --git a/trunk/src/core/srs_core_hls.cpp b/trunk/src/core/srs_core_hls.cpp index 6f0f3ec12..efe8e2ee8 100644 --- a/trunk/src/core/srs_core_hls.cpp +++ b/trunk/src/core/srs_core_hls.cpp @@ -41,6 +41,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include #include +#include // max PES packets size to flush the video. #define SRS_HLS_AUDIO_CACHE_SIZE 512 * 1024 @@ -1110,6 +1111,8 @@ SrsHls::SrsHls() muxer = new SrsM3u8Muxer(); ts_cache = new SrsTSCache(); + + pithy_print = new SrsPithyPrint(SRS_STAGE_HLS); } SrsHls::~SrsHls() @@ -1120,6 +1123,8 @@ SrsHls::~SrsHls() srs_freep(muxer); srs_freep(ts_cache); + + srs_freep(pithy_print); } int SrsHls::on_publish(SrsRequest* req) @@ -1328,8 +1333,20 @@ int SrsHls::on_video(SrsSharedPtrMessage* video) return ret; } + _mpegts(); + return ret; } +void SrsHls::_mpegts() +{ + // reportable + if (pithy_print->can_print()) { + srs_trace("-> time=%"PRId64"", pithy_print->get_age()); + } + + pithy_print->elapse(sample->cts); +} + #endif diff --git a/trunk/src/core/srs_core_hls.hpp b/trunk/src/core/srs_core_hls.hpp index 8b326ac7d..df7e12d19 100644 --- a/trunk/src/core/srs_core_hls.hpp +++ b/trunk/src/core/srs_core_hls.hpp @@ -43,6 +43,7 @@ class SrsRtmpJitter; class SrsTSMuxer; class SrsCodec; class SrsRequest; +class SrsPithyPrint; /** * jitter correct for audio, @@ -211,6 +212,7 @@ private: SrsCodec* codec; SrsCodecSample* sample; SrsRtmpJitter* jitter; + SrsPithyPrint* pithy_print; public: SrsHls(); virtual ~SrsHls(); @@ -220,6 +222,8 @@ public: virtual int on_meta_data(SrsOnMetaDataPacket* metadata); virtual int on_audio(SrsSharedPtrMessage* audio); virtual int on_video(SrsSharedPtrMessage* video); +private: + virtual void _mpegts(); }; #endif diff --git a/trunk/src/core/srs_core_pithy_print.cpp b/trunk/src/core/srs_core_pithy_print.cpp index 43059841d..3323a10bb 100644 --- a/trunk/src/core/srs_core_pithy_print.cpp +++ b/trunk/src/core/srs_core_pithy_print.cpp @@ -35,6 +35,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define SRS_STAGE_PLAY_USER_INTERVAL_MS 1300 #define SRS_STAGE_PUBLISH_USER_INTERVAL_MS 1100 #define SRS_STAGE_FORWARDER_INTERVAL_MS 2000 +#define SRS_STAGE_ENCODER_INTERVAL_MS 2000 +#define SRS_STAGE_HLS_INTERVAL_MS 2000 struct SrsStageInfo : public SrsReloadHandler { @@ -82,6 +84,22 @@ struct SrsStageInfo : public SrsReloadHandler } break; } + case SRS_STAGE_ENCODER: { + pithy_print_time_ms = SRS_STAGE_ENCODER_INTERVAL_MS; + SrsConfDirective* conf = config->get_pithy_print_encoder(); + if (conf && !conf->arg0().empty()) { + pithy_print_time_ms = ::atoi(conf->arg0().c_str()); + } + break; + } + case SRS_STAGE_HLS: { + pithy_print_time_ms = SRS_STAGE_HLS_INTERVAL_MS; + SrsConfDirective* conf = config->get_pithy_print_hls(); + if (conf && !conf->arg0().empty()) { + pithy_print_time_ms = ::atoi(conf->arg0().c_str()); + } + break; + } default: { pithy_print_time_ms = SRS_STAGE_DEFAULT_INTERVAL_MS; break; diff --git a/trunk/src/core/srs_core_pithy_print.hpp b/trunk/src/core/srs_core_pithy_print.hpp index 102c21cbb..9a86c0e8d 100644 --- a/trunk/src/core/srs_core_pithy_print.hpp +++ b/trunk/src/core/srs_core_pithy_print.hpp @@ -36,6 +36,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define SRS_STAGE_PUBLISH_USER 2 // the pithy stage for all forward clients. #define SRS_STAGE_FORWARDER 3 +// the pithy stage for all encoders. +#define SRS_STAGE_ENCODER 4 +// the pithy stage for all hls. +#define SRS_STAGE_HLS 5 /** * the stage is used for a collection of object to do print, diff --git a/trunk/src/main/srs_main_server.cpp b/trunk/src/main/srs_main_server.cpp index 766ffa13a..94d6fc31e 100644 --- a/trunk/src/main/srs_main_server.cpp +++ b/trunk/src/main/srs_main_server.cpp @@ -48,6 +48,8 @@ int main(int argc, char** argv){ return ret; } + // TODO: create log dir in config->get_log_dir() + if ((ret = _server()->listen()) != ERROR_SUCCESS) { return ret; } diff --git a/trunk/src/srs/srs.upp b/trunk/src/srs/srs.upp old mode 100644 new mode 100755 index 1129baaa8..fc7efce4c --- a/trunk/src/srs/srs.upp +++ b/trunk/src/srs/srs.upp @@ -1,57 +1,58 @@ file - main readonly separator, - ..\main\srs_main_server.cpp, - auto readonly separator, - ..\..\objs\srs_auto_headers.hpp, - core readonly separator, - ..\core\srs_core.hpp, - ..\core\srs_core.cpp, - ..\core\srs_core_error.hpp, - ..\core\srs_core_error.cpp, - ..\core\srs_core_autofree.hpp, - ..\core\srs_core_autofree.cpp, - ..\core\srs_core_server.hpp, - ..\core\srs_core_server.cpp, - ..\core\srs_core_reload.hpp, - ..\core\srs_core_reload.cpp, - ..\core\srs_core_config.hpp, - ..\core\srs_core_config.cpp, - ..\core\srs_core_refer.hpp, - ..\core\srs_core_refer.cpp, - ..\core\srs_core_conn.hpp, - ..\core\srs_core_conn.cpp, - ..\core\srs_core_client.hpp, - ..\core\srs_core_client.cpp, - ..\core\srs_core_source.hpp, - ..\core\srs_core_source.cpp, - ..\core\srs_core_forward.hpp, - ..\core\srs_core_forward.cpp, - ..\core\srs_core_encoder.hpp, - ..\core\srs_core_encoder.cpp, - ..\core\srs_core_hls.hpp, - ..\core\srs_core_hls.cpp, - ..\core\srs_core_codec.hpp, - ..\core\srs_core_codec.cpp, - ..\core\srs_core_rtmp.hpp, - ..\core\srs_core_rtmp.cpp, - ..\core\srs_core_handshake.hpp, - ..\core\srs_core_handshake.cpp, - ..\core\srs_core_protocol.hpp, - ..\core\srs_core_protocol.cpp, - ..\core\srs_core_amf0.hpp, - ..\core\srs_core_amf0.cpp, - ..\core\srs_core_stream.hpp, - ..\core\srs_core_stream.cpp, - ..\core\srs_core_socket.hpp, - ..\core\srs_core_socket.cpp, - ..\core\srs_core_buffer.hpp, - ..\core\srs_core_buffer.cpp, - ..\core\srs_core_pithy_print.hpp, - ..\core\srs_core_pithy_print.cpp, - ..\core\srs_core_log.hpp, - ..\core\srs_core_log.cpp, - research readonly separator, - ..\..\research\ts_info.cc; + main readonly separator, + ..\main\srs_main_server.cpp, + auto readonly separator, + ..\..\objs\srs_auto_headers.hpp, + core readonly separator, + ..\core\srs_core.hpp, + ..\core\srs_core.cpp, + ..\core\srs_core_error.hpp, + ..\core\srs_core_error.cpp, + ..\core\srs_core_autofree.hpp, + ..\core\srs_core_autofree.cpp, + ..\core\srs_core_server.hpp, + ..\core\srs_core_server.cpp, + ..\core\srs_core_reload.hpp, + ..\core\srs_core_reload.cpp, + ..\core\srs_core_config.hpp, + ..\core\srs_core_config.cpp, + ..\core\srs_core_refer.hpp, + ..\core\srs_core_refer.cpp, + ..\core\srs_core_conn.hpp, + ..\core\srs_core_conn.cpp, + ..\core\srs_core_client.hpp, + ..\core\srs_core_client.cpp, + ..\core\srs_core_source.hpp, + ..\core\srs_core_source.cpp, + ..\core\srs_core_forward.hpp, + ..\core\srs_core_forward.cpp, + ..\core\srs_core_encoder.hpp, + ..\core\srs_core_encoder.cpp, + ..\core\srs_core_hls.hpp, + ..\core\srs_core_hls.cpp, + ..\core\srs_core_codec.hpp, + ..\core\srs_core_codec.cpp, + ..\core\srs_core_rtmp.hpp, + ..\core\srs_core_rtmp.cpp, + ..\core\srs_core_handshake.hpp, + ..\core\srs_core_handshake.cpp, + ..\core\srs_core_protocol.hpp, + ..\core\srs_core_protocol.cpp, + ..\core\srs_core_amf0.hpp, + ..\core\srs_core_amf0.cpp, + ..\core\srs_core_stream.hpp, + ..\core\srs_core_stream.cpp, + ..\core\srs_core_socket.hpp, + ..\core\srs_core_socket.cpp, + ..\core\srs_core_buffer.hpp, + ..\core\srs_core_buffer.cpp, + ..\core\srs_core_pithy_print.hpp, + ..\core\srs_core_pithy_print.cpp, + ..\core\srs_core_log.hpp, + ..\core\srs_core_log.cpp, + research readonly separator, + ..\..\research\ts_info.cc; + mainconfig "" = "MAIN";