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