diff --git a/trunk/auto/build_ffmpeg.sh b/trunk/auto/build_ffmpeg.sh index 8748224cd..2bf106508 100755 --- a/trunk/auto/build_ffmpeg.sh +++ b/trunk/auto/build_ffmpeg.sh @@ -19,9 +19,6 @@ echo "SRS_JOBS: ${SRS_JOBS}" mkdir -p ${ff_build_dir} mkdir -p ${ff_release_dir} -# for ubuntu14, donot compile libaacplus. -UBUNTU14=NO;grep -in "Ubuntu 14." /etc/issue >/dev/null 2>&1; if [[ $? -eq 0 ]]; then UBUNTU14=YES; fi - # yasm for libx264 ff_yasm_bin=${ff_release_dir}/bin/yasm if [[ -f ${ff_yasm_bin} ]]; then diff --git a/trunk/configure b/trunk/configure index c234a810f..57444e793 100755 --- a/trunk/configure +++ b/trunk/configure @@ -138,7 +138,7 @@ if [ $SRS_MIPS_UBUNTU12 = YES ]; then SrsLinkOptions="${SrsLinkOptions} -lgcc_eh MODULE_ID="CORE" MODULE_DEPENDS=() ModuleLibIncs=(${SRS_OBJS_DIR}) -MODULE_FILES=("srs_core" "srs_core_autofree" "srs_core_performance") +MODULE_FILES=("srs_core" "srs_core_autofree" "srs_core_performance" "srs_core_mem_watch") CORE_INCS="src/core"; MODULE_DIR=${CORE_INCS} . auto/modules.sh CORE_OBJS="${MODULE_OBJS[@]}" # diff --git a/trunk/ide/srs_upp/srs_upp.upp b/trunk/ide/srs_upp/srs_upp.upp index 764b0ee0b..e80292576 100755 --- a/trunk/ide/srs_upp/srs_upp.upp +++ b/trunk/ide/srs_upp/srs_upp.upp @@ -16,6 +16,8 @@ file ../../src/core/srs_core.cpp, ../../src/core/srs_core_autofree.hpp, ../../src/core/srs_core_autofree.cpp, + ../../src/core/srs_core_mem_watch.hpp, + ../../src/core/srs_core_mem_watch.cpp, ../../src/core/srs_core_performance.hpp, ../../src/core/srs_core_performance.cpp, kernel readonly separator, diff --git a/trunk/ide/srs_vs2010/srs.vcxproj b/trunk/ide/srs_vs2010/srs.vcxproj index de224841c..5ddd7892f 100755 --- a/trunk/ide/srs_vs2010/srs.vcxproj +++ b/trunk/ide/srs_vs2010/srs.vcxproj @@ -100,6 +100,7 @@ + @@ -181,6 +182,7 @@ + diff --git a/trunk/ide/srs_xcode/srs_xcode.xcodeproj/project.pbxproj b/trunk/ide/srs_xcode/srs_xcode.xcodeproj/project.pbxproj index 08f2ecc7f..a6fbb1079 100644 --- a/trunk/ide/srs_xcode/srs_xcode.xcodeproj/project.pbxproj +++ b/trunk/ide/srs_xcode/srs_xcode.xcodeproj/project.pbxproj @@ -79,6 +79,7 @@ 3C36DB5B1ABD1CB90066CCAF /* srs_lib_bandwidth.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C36DB551ABD1CB90066CCAF /* srs_lib_bandwidth.cpp */; }; 3C36DB5C1ABD1CB90066CCAF /* srs_lib_simple_socket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C36DB571ABD1CB90066CCAF /* srs_lib_simple_socket.cpp */; }; 3C36DB5D1ABD1CB90066CCAF /* srs_librtmp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C36DB591ABD1CB90066CCAF /* srs_librtmp.cpp */; }; + 3C5265B41B241BF0009CA186 /* srs_core_mem_watch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C5265B21B241BF0009CA186 /* srs_core_mem_watch.cpp */; }; 3C663F0F1AB0155100286D8B /* srs_aac_raw_publish.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C663F021AB0155100286D8B /* srs_aac_raw_publish.c */; }; 3C663F101AB0155100286D8B /* srs_audio_raw_publish.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C663F031AB0155100286D8B /* srs_audio_raw_publish.c */; }; 3C663F111AB0155100286D8B /* srs_bandwidth_check.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C663F041AB0155100286D8B /* srs_bandwidth_check.c */; }; @@ -327,6 +328,8 @@ 3C36DB581ABD1CB90066CCAF /* srs_lib_simple_socket.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_lib_simple_socket.hpp; path = ../../../src/libs/srs_lib_simple_socket.hpp; sourceTree = ""; }; 3C36DB591ABD1CB90066CCAF /* srs_librtmp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_librtmp.cpp; path = ../../../src/libs/srs_librtmp.cpp; sourceTree = ""; }; 3C36DB5A1ABD1CB90066CCAF /* srs_librtmp.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_librtmp.hpp; path = ../../../src/libs/srs_librtmp.hpp; sourceTree = ""; }; + 3C5265B21B241BF0009CA186 /* srs_core_mem_watch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_core_mem_watch.cpp; path = ../../../src/core/srs_core_mem_watch.cpp; sourceTree = ""; }; + 3C5265B31B241BF0009CA186 /* srs_core_mem_watch.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_core_mem_watch.hpp; path = ../../../src/core/srs_core_mem_watch.hpp; sourceTree = ""; }; 3C663F021AB0155100286D8B /* srs_aac_raw_publish.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = srs_aac_raw_publish.c; path = ../../../research/librtmp/srs_aac_raw_publish.c; sourceTree = ""; }; 3C663F031AB0155100286D8B /* srs_audio_raw_publish.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = srs_audio_raw_publish.c; path = ../../../research/librtmp/srs_audio_raw_publish.c; sourceTree = ""; }; 3C663F041AB0155100286D8B /* srs_bandwidth_check.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = srs_bandwidth_check.c; path = ../../../research/librtmp/srs_bandwidth_check.c; sourceTree = ""; }; @@ -428,6 +431,8 @@ children = ( 3C1231F01AAE652C00CE8F6C /* srs_core_autofree.cpp */, 3C1231F11AAE652C00CE8F6C /* srs_core_autofree.hpp */, + 3C5265B21B241BF0009CA186 /* srs_core_mem_watch.cpp */, + 3C5265B31B241BF0009CA186 /* srs_core_mem_watch.hpp */, 3C1231F21AAE652C00CE8F6C /* srs_core_performance.cpp */, 3C1231F31AAE652C00CE8F6C /* srs_core_performance.hpp */, 3C1231F41AAE652D00CE8F6C /* srs_core.cpp */, @@ -882,6 +887,7 @@ 3CC52DDC1ACE4023006FEB01 /* srs_utest_protocol.cpp in Sources */, 3C663F151AB0155100286D8B /* srs_h264_raw_publish.c in Sources */, 3C1231F61AAE652D00CE8F6C /* srs_core_autofree.cpp in Sources */, + 3C5265B41B241BF0009CA186 /* srs_core_mem_watch.cpp in Sources */, 3C1EE6D71AB1367D00576EE9 /* README.md in Sources */, 3C1232411AAE81A400CE8F6C /* srs_raw_avc.cpp in Sources */, 3C1232491AAE81A400CE8F6C /* srs_rtmp_utility.cpp in Sources */, diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 082f2efda..a62765a38 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -2860,13 +2860,15 @@ vector SrsConfig::get_engine_vfilter(SrsConfDirective* engine) string SrsConfig::get_engine_vcodec(SrsConfDirective* engine) { + static string DEFAULT = ""; + if (!engine) { - return ""; + return DEFAULT; } SrsConfDirective* conf = engine->get("vcodec"); if (!conf) { - return ""; + return DEFAULT; } return conf->arg0(); @@ -2998,13 +3000,15 @@ vector SrsConfig::get_engine_vparams(SrsConfDirective* engine) string SrsConfig::get_engine_acodec(SrsConfDirective* engine) { + static string DEFAULT = ""; + if (!engine) { - return ""; + return DEFAULT; } SrsConfDirective* conf = engine->get("acodec"); if (!conf) { - return ""; + return DEFAULT; } return conf->arg0(); diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index eb0374540..c80e82bcf 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -783,7 +783,7 @@ public: virtual std::vector get_engine_vfilter(SrsConfDirective* engine); /** * get the vcodec of engine, - * the codec of video, copy or libx264 + * the codec of video, can be vn, copy or libx264 */ virtual std::string get_engine_vcodec(SrsConfDirective* engine); /** @@ -827,7 +827,7 @@ public: virtual std::vector get_engine_vparams(SrsConfDirective* engine); /** * get the acodec of engine, - * the audio codec can be copy or libaacplus + * the audio codec can be an, copy or libfdk_aac */ virtual std::string get_engine_acodec(SrsConfDirective* engine); /** diff --git a/trunk/src/app/srs_app_conn.cpp b/trunk/src/app/srs_app_conn.cpp index a03a17489..8cedcfec3 100644 --- a/trunk/src/app/srs_app_conn.cpp +++ b/trunk/src/app/srs_app_conn.cpp @@ -40,6 +40,7 @@ SrsConnection::SrsConnection(IConnectionManager* cm, st_netfd_t c) id = 0; manager = cm; stfd = c; + disposed = false; // the client thread should reap itself, // so we never use joinable. @@ -50,12 +51,24 @@ SrsConnection::SrsConnection(IConnectionManager* cm, st_netfd_t c) SrsConnection::~SrsConnection() { + dispose(); + + srs_freep(pthread); +} + +void SrsConnection::dispose() +{ + if (disposed) { + return; + } + + disposed = true; + /** * when delete the connection, stop the connection, * close the underlayer socket, delete the thread. */ srs_close_stfd(stfd); - srs_freep(pthread); } int SrsConnection::start() diff --git a/trunk/src/app/srs_app_conn.hpp b/trunk/src/app/srs_app_conn.hpp index e1845406c..e9426c395 100644 --- a/trunk/src/app/srs_app_conn.hpp +++ b/trunk/src/app/srs_app_conn.hpp @@ -83,10 +83,19 @@ protected: * the ip of client. */ std::string ip; + /** + * whether the connection is disposed, + * when disposed, connection should stop cycle and cleanup itself. + */; + bool disposed; public: SrsConnection(IConnectionManager* cm, st_netfd_t c); virtual ~SrsConnection(); public: + /** + * to dipose the connection. + */ + virtual void dispose(); /** * start the client green thread. * when server get a client from listener, diff --git a/trunk/src/app/srs_app_ffmpeg.cpp b/trunk/src/app/srs_app_ffmpeg.cpp index 53b24f06f..79fcd39dd 100644 --- a/trunk/src/app/srs_app_ffmpeg.cpp +++ b/trunk/src/app/srs_app_ffmpeg.cpp @@ -48,6 +48,7 @@ using namespace std; // for example, libaacplus, aac, fdkaac #define SRS_RTMP_ENCODER_ACODEC "aac" #define SRS_RTMP_ENCODER_LIBAACPLUS "libaacplus" +#define SRS_RTMP_ENCODER_LIBFDKAAC "libfdk_aac" SrsFFMPEG::SrsFFMPEG(std::string ffmpeg_bin) { @@ -174,7 +175,7 @@ int SrsFFMPEG::initialize_transcode(SrsConfDirective* engine) } // @see, https://github.com/simple-rtmp-server/srs/issues/145 - if (acodec == SRS_RTMP_ENCODER_LIBAACPLUS) { + if (acodec == SRS_RTMP_ENCODER_LIBAACPLUS && acodec != SRS_RTMP_ENCODER_LIBFDKAAC) { if (abitrate < 16 || abitrate > 72) { ret = ERROR_ENCODER_ABITRATE; srs_error("invalid abitrate for aac: %d, must in [16, 72], ret=%d", abitrate, ret); diff --git a/trunk/src/app/srs_app_http_api.cpp b/trunk/src/app/srs_app_http_api.cpp index 393943f34..6b25c9544 100644 --- a/trunk/src/app/srs_app_http_api.cpp +++ b/trunk/src/app/srs_app_http_api.cpp @@ -529,7 +529,7 @@ int SrsHttpApi::do_cycle() skt.set_recv_timeout(SRS_HTTP_RECV_TIMEOUT_US); // process http messages. - for (;;) { + while(!disposed) { ISrsHttpMessage* req = NULL; // get a http message diff --git a/trunk/src/app/srs_app_http_conn.cpp b/trunk/src/app/srs_app_http_conn.cpp index 3caf7f28a..4f7cac5bd 100644 --- a/trunk/src/app/srs_app_http_conn.cpp +++ b/trunk/src/app/srs_app_http_conn.cpp @@ -2533,7 +2533,7 @@ int SrsHttpConn::do_cycle() skt.set_recv_timeout(SRS_HTTP_RECV_TIMEOUT_US); // process http messages. - for (;;) { + while (!disposed) { ISrsHttpMessage* req = NULL; // get a http message diff --git a/trunk/src/app/srs_app_rtmp_conn.cpp b/trunk/src/app/srs_app_rtmp_conn.cpp index a1e9815db..a72dcfc9e 100644 --- a/trunk/src/app/srs_app_rtmp_conn.cpp +++ b/trunk/src/app/srs_app_rtmp_conn.cpp @@ -320,11 +320,14 @@ int SrsRtmpConn::service_cycle() } srs_verbose("on_bw_done success"); - while (true) { + while (!disposed) { ret = stream_service_cycle(); // stream service must terminated with error, never success. - srs_assert(ret != ERROR_SUCCESS); + // when terminated with success, it's user required to stop. + if (ret == ERROR_SUCCESS) { + continue; + } // when not system control error, fatal error, return. if (!srs_is_system_control_error(ret)) { @@ -361,6 +364,8 @@ int SrsRtmpConn::service_cycle() srs_error("control message(%d) reject as error. ret=%d", ret, ret); return ret; } + + return ret; } int SrsRtmpConn::stream_service_cycle() @@ -635,7 +640,7 @@ int SrsRtmpConn::do_playing(SrsSource* source, SrsConsumer* consumer, SrsQueueRe // set the sock options. play_set_sock_options(); - while (true) { + while (!disposed) { // collect elapse for pithy print. pprint->elapse(); @@ -865,7 +870,7 @@ int SrsRtmpConn::do_publishing(SrsSource* source, SrsPublishRecvThread* trd) } int64_t nb_msgs = 0; - while (true) { + while (!disposed) { pprint->elapse(); // cond wait for error. diff --git a/trunk/src/app/srs_app_server.cpp b/trunk/src/app/srs_app_server.cpp index 1fcfff052..575372d83 100644 --- a/trunk/src/app/srs_app_server.cpp +++ b/trunk/src/app/srs_app_server.cpp @@ -47,6 +47,7 @@ using namespace std; #include #include #include +#include // signal defines. #define SIGNAL_RELOAD SIGHUP @@ -513,15 +514,7 @@ void SrsServer::destroy() { srs_warn("start destroy server"); - _srs_config->unsubscribe(this); - - close_listeners(SrsListenerRtmpStream); - close_listeners(SrsListenerHttpApi); - close_listeners(SrsListenerHttpStream); - -#ifdef SRS_AUTO_INGEST - ingester->dispose(); -#endif + dispose(); #ifdef SRS_AUTO_HTTP_API srs_freep(http_api_mux); @@ -547,28 +540,39 @@ void SrsServer::destroy() srs_freep(signal_manager); srs_freep(handler); - - // @remark never destroy the connections, - // for it's still alive. - - // @remark never destroy the source, - // when we free all sources, the fmle publish may retry - // and segment fault. } void SrsServer::dispose() { _srs_config->unsubscribe(this); + // prevent fresh clients. + close_listeners(SrsListenerRtmpStream); + close_listeners(SrsListenerHttpApi); + close_listeners(SrsListenerHttpStream); + close_listeners(SrsListenerMpegTsOverUdp); + close_listeners(SrsListenerRtsp); + close_listeners(SrsListenerFlv); + #ifdef SRS_AUTO_INGEST ingester->dispose(); - srs_trace("gracefully dispose ingesters"); #endif SrsSource::dispose_all(); - srs_trace("gracefully dispose sources"); - srs_trace("terminate server"); + while (!conns.empty()) { + std::vector::iterator it; + for (it = conns.begin(); it != conns.end(); ++it) { + SrsConnection* conn = *it; + conn->dispose(); + } + + st_usleep(100 * 1000); + } + +#ifdef SRS_MEM_WATCH + srs_memory_report(); +#endif } int SrsServer::initialize(ISrsServerCycle* cycle_handler) @@ -889,6 +893,9 @@ void SrsServer::on_signal(int signo) signal_gmc_stop = true; #else srs_trace("user terminate program"); +#ifdef SRS_MEM_WATCH + srs_memory_report(); +#endif exit(0); #endif return; diff --git a/trunk/src/app/srs_app_source.cpp b/trunk/src/app/srs_app_source.cpp index 72d0f08c2..32b9cae39 100755 --- a/trunk/src/app/srs_app_source.cpp +++ b/trunk/src/app/srs_app_source.cpp @@ -583,6 +583,11 @@ SrsGopCache::~SrsGopCache() clear(); } +void SrsGopCache::dispose() +{ + clear(); +} + void SrsGopCache::set(bool enabled) { enable_gop_cache = enabled; @@ -955,6 +960,14 @@ void SrsSource::dispose() #ifdef SRS_AUTO_HLS hls->dispose(); #endif + + // cleaup the cached packets. + srs_freep(cache_metadata); + srs_freep(cache_sh_video); + srs_freep(cache_sh_audio); + + // cleanup the gop cache. + gop_cache->dispose(); } int SrsSource::cycle() diff --git a/trunk/src/app/srs_app_source.hpp b/trunk/src/app/srs_app_source.hpp index bdb4d5f4c..95eda44ea 100644 --- a/trunk/src/app/srs_app_source.hpp +++ b/trunk/src/app/srs_app_source.hpp @@ -309,6 +309,10 @@ public: SrsGopCache(); virtual ~SrsGopCache(); public: + /** + * cleanup when system quit. + */ + virtual void dispose(); /** * to enable or disable the gop cache. */ diff --git a/trunk/src/core/srs_core_mem_watch.cpp b/trunk/src/core/srs_core_mem_watch.cpp new file mode 100644 index 000000000..bbdcbc7bb --- /dev/null +++ b/trunk/src/core/srs_core_mem_watch.cpp @@ -0,0 +1,85 @@ +/* +The MIT License (MIT) + +Copyright (c) 2013-2015 SRS(simple-rtmp-server) + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include + +#ifdef SRS_MEM_WATCH + +#include +#include +using namespace std; + +struct SrsMemoryObject +{ + void* ptr; + std::string category; + int size; +}; + +std::map _srs_ptrs; + +void srs_memory_watch(void* ptr, string category, int size) +{ + SrsMemoryObject* obj = NULL; + + std::map::iterator it; + if ((it = _srs_ptrs.find(ptr)) != _srs_ptrs.end()) { + obj = it->second; + } else { + obj = new SrsMemoryObject(); + _srs_ptrs[ptr] = obj; + } + + obj->ptr = ptr; + obj->category = category; + obj->size = size; +} + +void srs_memory_unwatch(void* ptr) +{ + std::map::iterator it; + if ((it = _srs_ptrs.find(ptr)) != _srs_ptrs.end()) { + SrsMemoryObject* obj = it->second; + srs_freep(obj); + + _srs_ptrs.erase(it); + } +} + +void srs_memory_report() +{ + printf("srs memory leak report:\n"); + + int total = 0; + std::map::iterator it; + for (it = _srs_ptrs.begin(); it != _srs_ptrs.end(); ++it) { + SrsMemoryObject* obj = it->second; + printf(" %s: %#"PRIx64", %dB\n", obj->category.c_str(), (int64_t)obj->ptr, obj->size); + total += obj->size; + } + + printf("%d objects leak %dKB.\n", (int)_srs_ptrs.size(), total / 1024); +} + +#endif + diff --git a/trunk/src/core/srs_core_mem_watch.hpp b/trunk/src/core/srs_core_mem_watch.hpp new file mode 100644 index 000000000..bcaf96304 --- /dev/null +++ b/trunk/src/core/srs_core_mem_watch.hpp @@ -0,0 +1,49 @@ +/* +The MIT License (MIT) + +Copyright (c) 2013-2015 SRS(simple-rtmp-server) + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef SRS_CORE_MEM_WATCH_HPP +#define SRS_CORE_MEM_WATCH_HPP + +/* +#include +*/ + +#include + +#ifdef SRS_MEM_WATCH + +#include + +// watch the specified memory. +extern void srs_memory_watch(void* ptr, std::string category, int size); + +// unwatch the specified memory. +extern void srs_memory_unwatch(void* ptr); + +// report the memory watch. +extern void srs_memory_report(); + +#endif + +#endif + diff --git a/trunk/src/core/srs_core_performance.hpp b/trunk/src/core/srs_core_performance.hpp index 407ca0fef..c1b924756 100644 --- a/trunk/src/core/srs_core_performance.hpp +++ b/trunk/src/core/srs_core_performance.hpp @@ -188,5 +188,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #undef SRS_PERF_FAST_FLV_ENCODER #define SRS_PERF_FAST_FLV_ENCODER +/** + * whether enable the special memory watcher. + * which used for memory leak debug and hurts performance. + */ +#define SRS_MEM_WATCH +#undef SRS_MEM_WATCH + #endif diff --git a/trunk/src/kernel/srs_kernel_flv.cpp b/trunk/src/kernel/srs_kernel_flv.cpp index 745b5b083..60bd3cfcc 100644 --- a/trunk/src/kernel/srs_kernel_flv.cpp +++ b/trunk/src/kernel/srs_kernel_flv.cpp @@ -38,6 +38,7 @@ using namespace std; #include #include #include +#include SrsMessageHeader::SrsMessageHeader() { @@ -159,6 +160,9 @@ SrsCommonMessage::SrsCommonMessage() SrsCommonMessage::~SrsCommonMessage() { +#ifdef SRS_MEM_WATCH + srs_memory_unwatch(payload); +#endif srs_freep(payload); } @@ -171,6 +175,9 @@ SrsSharedPtrMessage::SrsSharedPtrPayload::SrsSharedPtrPayload() SrsSharedPtrMessage::SrsSharedPtrPayload::~SrsSharedPtrPayload() { +#ifdef SRS_MEM_WATCH + srs_memory_unwatch(payload); +#endif srs_freep(payload); } diff --git a/trunk/src/main/srs_main_server.cpp b/trunk/src/main/srs_main_server.cpp index fddd9702b..d0750f2fe 100644 --- a/trunk/src/main/srs_main_server.cpp +++ b/trunk/src/main/srs_main_server.cpp @@ -211,6 +211,11 @@ void check_macro_features() #warning "current branch is not stable, please use stable branch instead." srs_warn("SRS %s is not stable, please use stable branch %s instead", RTMP_SIG_SRS_VERSION, VERSION_STABLE_BRANCH); #endif + +#ifdef SRS_MEM_WATCH + #warning "srs memory watcher will hurts performance. user should kill by SIGTERM or init.d script." + srs_warn("srs memory watcher will hurts performance. user should kill by SIGTERM or init.d script."); +#endif #if defined(SRS_AUTO_STREAM_CASTER) #warning "stream caster is experiment feature." diff --git a/trunk/src/protocol/srs_protocol_buffer.cpp b/trunk/src/protocol/srs_protocol_buffer.cpp index 176131282..9efa26d78 100644 --- a/trunk/src/protocol/srs_protocol_buffer.cpp +++ b/trunk/src/protocol/srs_protocol_buffer.cpp @@ -72,7 +72,7 @@ SrsFastBuffer::~SrsFastBuffer() int SrsFastBuffer::size() { - return end - p; + return (int)(end - p); } char* SrsFastBuffer::bytes() diff --git a/trunk/src/protocol/srs_rtmp_stack.cpp b/trunk/src/protocol/srs_rtmp_stack.cpp index 738a7d81f..b4893955a 100644 --- a/trunk/src/protocol/srs_rtmp_stack.cpp +++ b/trunk/src/protocol/srs_rtmp_stack.cpp @@ -30,6 +30,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include #include +#include // for srs-librtmp, @see https://github.com/simple-rtmp-server/srs/issues/213 #ifndef _WIN32 @@ -364,6 +365,7 @@ int SrsProtocol::recv_message(SrsCommonMessage** pmsg) srs_verbose("entire msg received"); if (!msg) { + srs_info("got empty message without error."); continue; } @@ -467,7 +469,7 @@ int SrsProtocol::do_send_messages(SrsSharedPtrMessage** msgs, int nb_msgs) iovs[0].iov_len = nbh; // payload iov - int payload_size = srs_min(out_chunk_size, pend - p); + int payload_size = srs_min(out_chunk_size, (int)(pend - p)); iovs[1].iov_base = p; iovs[1].iov_len = payload_size; @@ -1411,6 +1413,9 @@ int SrsProtocol::read_message_payload(SrsChunkStream* chunk, SrsCommonMessage** if (!chunk->msg->payload) { chunk->msg->payload = new char[chunk->header.payload_length]; srs_verbose("create payload for RTMP message. size=%d", chunk->header.payload_length); +#ifdef SRS_MEM_WATCH + srs_memory_watch(chunk->msg->payload, "msg.payload", chunk->header.payload_length); +#endif } // read payload to buffer diff --git a/trunk/src/utest/srs_utest_config.cpp b/trunk/src/utest/srs_utest_config.cpp index 521db6685..9406701fa 100644 --- a/trunk/src/utest/srs_utest_config.cpp +++ b/trunk/src/utest/srs_utest_config.cpp @@ -289,7 +289,7 @@ std::string _full_conf = "" " bf 3; \n " " refs 10; \n " " } \n " -" acodec libaacplus; \n " +" acodec libfdk_aac; \n " " abitrate 70; \n " " asample_rate 44100; \n " " achannels 2; \n " @@ -320,7 +320,7 @@ std::string _full_conf = "" " vpreset superfast; \n " " vparams { \n " " } \n " -" acodec libaacplus; \n " +" acodec libfdk_aac; \n " " abitrate 45; \n " " asample_rate 44100; \n " " achannels 2; \n " @@ -349,7 +349,7 @@ std::string _full_conf = "" " vpreset superfast; \n " " vparams { \n " " } \n " -" acodec libaacplus; \n " +" acodec libfdk_aac; \n " " abitrate 45; \n " " asample_rate 44100; \n " " achannels 2; \n " @@ -379,7 +379,7 @@ std::string _full_conf = "" " vpreset superfast; \n " " vparams { \n " " } \n " -" acodec libaacplus; \n " +" acodec libfdk_aac; \n " " abitrate 45; \n " " asample_rate 44100; \n " " achannels 2; \n " @@ -396,7 +396,7 @@ std::string _full_conf = "" " engine acodec { \n " " enabled on; \n " " vcodec copy; \n " -" acodec libaacplus; \n " +" acodec libfdk_aac; \n " " abitrate 45; \n " " asample_rate 44100; \n " " achannels 2; \n " @@ -413,7 +413,7 @@ std::string _full_conf = "" " engine vn { \n " " enabled on; \n " " vcodec vn; \n " -" acodec libaacplus; \n " +" acodec libfdk_aac; \n " " abitrate 45; \n " " asample_rate 44100; \n " " achannels 2; \n " @@ -461,7 +461,7 @@ std::string _full_conf = "" " bf 3; \n " " refs 10; \n " " } \n " -" acodec libaacplus; \n " +" acodec libfdk_aac; \n " " abitrate 70; \n " " asample_rate 44100; \n " " achannels 2; \n " @@ -483,7 +483,7 @@ std::string _full_conf = "" " vpreset medium; \n " " vparams { \n " " } \n " -" acodec libaacplus; \n " +" acodec libfdk_aac; \n " " abitrate 70; \n " " asample_rate 44100; \n " " achannels 2; \n " @@ -503,7 +503,7 @@ std::string _full_conf = "" " vpreset fast; \n " " vparams { \n " " } \n " -" acodec libaacplus; \n " +" acodec libfdk_aac; \n " " abitrate 60; \n " " asample_rate 44100; \n " " achannels 2; \n " @@ -523,7 +523,7 @@ std::string _full_conf = "" " vpreset superfast; \n " " vparams { \n " " } \n " -" acodec libaacplus; \n " +" acodec libfdk_aac; \n " " abitrate 45; \n " " asample_rate 44100; \n " " achannels 2; \n " @@ -534,7 +534,7 @@ std::string _full_conf = "" " engine vcopy { \n " " enabled on; \n " " vcodec copy; \n " -" acodec libaacplus; \n " +" acodec libfdk_aac; \n " " abitrate 45; \n " " asample_rate 44100; \n " " achannels 2; \n " @@ -581,7 +581,7 @@ std::string _full_conf = "" " vpreset superfast; \n " " vparams { \n " " } \n " -" acodec libaacplus; \n " +" acodec libfdk_aac; \n " " abitrate 45; \n " " asample_rate 44100; \n " " achannels 2; \n " @@ -2586,7 +2586,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_transcode_mirror) EXPECT_STREQ("baseline", conf.get_engine_vprofile(engine).c_str()); EXPECT_STREQ("superfast", conf.get_engine_vpreset(engine).c_str()); EXPECT_TRUE((int)conf.get_engine_vparams(engine).size() == 0); - EXPECT_STREQ("libaacplus", conf.get_engine_acodec(engine).c_str()); + EXPECT_STREQ("libfdk_aac", conf.get_engine_acodec(engine).c_str()); EXPECT_EQ(45, conf.get_engine_abitrate(engine)); EXPECT_EQ(44100, conf.get_engine_asample_rate(engine)); EXPECT_EQ(2, conf.get_engine_achannels(engine)); @@ -2676,7 +2676,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_transcode_crop) EXPECT_STREQ("baseline", conf.get_engine_vprofile(engine).c_str()); EXPECT_STREQ("superfast", conf.get_engine_vpreset(engine).c_str()); EXPECT_TRUE((int)conf.get_engine_vparams(engine).size() == 0); - EXPECT_STREQ("libaacplus", conf.get_engine_acodec(engine).c_str()); + EXPECT_STREQ("libfdk_aac", conf.get_engine_acodec(engine).c_str()); EXPECT_EQ(45, conf.get_engine_abitrate(engine)); EXPECT_EQ(44100, conf.get_engine_asample_rate(engine)); EXPECT_EQ(2, conf.get_engine_achannels(engine)); @@ -2766,7 +2766,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_transcode_logo) EXPECT_STREQ("baseline", conf.get_engine_vprofile(engine).c_str()); EXPECT_STREQ("superfast", conf.get_engine_vpreset(engine).c_str()); EXPECT_TRUE((int)conf.get_engine_vparams(engine).size() == 0); - EXPECT_STREQ("libaacplus", conf.get_engine_acodec(engine).c_str()); + EXPECT_STREQ("libfdk_aac", conf.get_engine_acodec(engine).c_str()); EXPECT_EQ(45, conf.get_engine_abitrate(engine)); EXPECT_EQ(44100, conf.get_engine_asample_rate(engine)); EXPECT_EQ(2, conf.get_engine_achannels(engine)); @@ -2849,7 +2849,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_transcode_audio) EXPECT_STREQ("flv", conf.get_engine_iformat(engine).c_str()); EXPECT_TRUE((int)conf.get_engine_vfilter(engine).size() == 0); EXPECT_STREQ("copy", conf.get_engine_vcodec(engine).c_str()); - EXPECT_STREQ("libaacplus", conf.get_engine_acodec(engine).c_str()); + EXPECT_STREQ("libfdk_aac", conf.get_engine_acodec(engine).c_str()); EXPECT_EQ(45, conf.get_engine_abitrate(engine)); EXPECT_EQ(44100, conf.get_engine_asample_rate(engine)); EXPECT_EQ(2, conf.get_engine_achannels(engine)); @@ -2933,7 +2933,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_transcode_vn) EXPECT_STREQ("flv", conf.get_engine_iformat(engine).c_str()); EXPECT_TRUE((int)conf.get_engine_vfilter(engine).size() == 0); EXPECT_STREQ("vn", conf.get_engine_vcodec(engine).c_str()); - EXPECT_STREQ("libaacplus", conf.get_engine_acodec(engine).c_str()); + EXPECT_STREQ("libfdk_aac", conf.get_engine_acodec(engine).c_str()); EXPECT_EQ(45, conf.get_engine_abitrate(engine)); EXPECT_EQ(44100, conf.get_engine_asample_rate(engine)); EXPECT_EQ(2, conf.get_engine_achannels(engine)); @@ -3105,7 +3105,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_transcode_all) EXPECT_STREQ("main", conf.get_engine_vprofile(engine).c_str()); EXPECT_STREQ("medium", conf.get_engine_vpreset(engine).c_str()); EXPECT_TRUE((int)conf.get_engine_vparams(engine).size() > 0); - EXPECT_STREQ("libaacplus", conf.get_engine_acodec(engine).c_str()); + EXPECT_STREQ("libfdk_aac", conf.get_engine_acodec(engine).c_str()); EXPECT_EQ(70, conf.get_engine_abitrate(engine)); EXPECT_EQ(44100, conf.get_engine_asample_rate(engine)); EXPECT_EQ(2, conf.get_engine_achannels(engine)); @@ -3130,7 +3130,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_transcode_all) EXPECT_STREQ("main", conf.get_engine_vprofile(engine).c_str()); EXPECT_STREQ("medium", conf.get_engine_vpreset(engine).c_str()); EXPECT_TRUE((int)conf.get_engine_vparams(engine).size() == 0); - EXPECT_STREQ("libaacplus", conf.get_engine_acodec(engine).c_str()); + EXPECT_STREQ("libfdk_aac", conf.get_engine_acodec(engine).c_str()); EXPECT_EQ(70, conf.get_engine_abitrate(engine)); EXPECT_EQ(44100, conf.get_engine_asample_rate(engine)); EXPECT_EQ(2, conf.get_engine_achannels(engine)); @@ -3155,7 +3155,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_transcode_all) EXPECT_STREQ("main", conf.get_engine_vprofile(engine).c_str()); EXPECT_STREQ("fast", conf.get_engine_vpreset(engine).c_str()); EXPECT_TRUE((int)conf.get_engine_vparams(engine).size() == 0); - EXPECT_STREQ("libaacplus", conf.get_engine_acodec(engine).c_str()); + EXPECT_STREQ("libfdk_aac", conf.get_engine_acodec(engine).c_str()); EXPECT_EQ(60, conf.get_engine_abitrate(engine)); EXPECT_EQ(44100, conf.get_engine_asample_rate(engine)); EXPECT_EQ(2, conf.get_engine_achannels(engine)); @@ -3180,7 +3180,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_transcode_all) EXPECT_STREQ("baseline", conf.get_engine_vprofile(engine).c_str()); EXPECT_STREQ("superfast", conf.get_engine_vpreset(engine).c_str()); EXPECT_TRUE((int)conf.get_engine_vparams(engine).size() == 0); - EXPECT_STREQ("libaacplus", conf.get_engine_acodec(engine).c_str()); + EXPECT_STREQ("libfdk_aac", conf.get_engine_acodec(engine).c_str()); EXPECT_EQ(45, conf.get_engine_abitrate(engine)); EXPECT_EQ(44100, conf.get_engine_asample_rate(engine)); EXPECT_EQ(2, conf.get_engine_achannels(engine)); @@ -3197,7 +3197,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_transcode_all) EXPECT_STREQ("flv", conf.get_engine_iformat(engine).c_str()); EXPECT_TRUE((int)conf.get_engine_vfilter(engine).size() == 0); EXPECT_STREQ("copy", conf.get_engine_vcodec(engine).c_str()); - EXPECT_STREQ("libaacplus", conf.get_engine_acodec(engine).c_str()); + EXPECT_STREQ("libfdk_aac", conf.get_engine_acodec(engine).c_str()); EXPECT_EQ(45, conf.get_engine_abitrate(engine)); EXPECT_EQ(44100, conf.get_engine_asample_rate(engine)); EXPECT_EQ(2, conf.get_engine_achannels(engine)); @@ -3322,7 +3322,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_transcode_ffempty) EXPECT_STREQ("baseline", conf.get_engine_vprofile(engine).c_str()); EXPECT_STREQ("superfast", conf.get_engine_vpreset(engine).c_str()); EXPECT_TRUE((int)conf.get_engine_vparams(engine).size() == 0); - EXPECT_STREQ("libaacplus", conf.get_engine_acodec(engine).c_str()); + EXPECT_STREQ("libfdk_aac", conf.get_engine_acodec(engine).c_str()); EXPECT_EQ(45, conf.get_engine_abitrate(engine)); EXPECT_EQ(44100, conf.get_engine_asample_rate(engine)); EXPECT_EQ(2, conf.get_engine_achannels(engine)); @@ -4837,12 +4837,12 @@ VOID TEST(ConfigMainTest, CheckConf_transcode) if (true) { MockSrsConfig conf; - EXPECT_TRUE(ERROR_SUCCESS == conf.parse(_MIN_OK_CONF"vhost v{transcode{engine {acodec libaacplus;}}}")); + EXPECT_TRUE(ERROR_SUCCESS == conf.parse(_MIN_OK_CONF"vhost v{transcode{engine {acodec libfdk_aac;}}}")); } if (true) { MockSrsConfig conf; - EXPECT_TRUE(ERROR_SUCCESS != conf.parse(_MIN_OK_CONF"vhost v{transcode{engine {acodecs libaacplus;}}}")); + EXPECT_TRUE(ERROR_SUCCESS != conf.parse(_MIN_OK_CONF"vhost v{transcode{engine {acodecs libfdk_aac;}}}")); } if (true) {