diff --git a/README.md b/README.md index 31410a17c..de37023f1 100755 --- a/README.md +++ b/README.md @@ -530,7 +530,8 @@ Supported operating systems and hardware: ### SRS 2.0 history -* v2.0, 2015-02-19, refine pithy print to more easyer to use 2.0.121. +* v2.0, 2015-02-19, refine dvr, append file when dvr file exists. 2.0.122. +* v2.0, 2015-02-19, refine pithy print to more easyer to use. 2.0.121. * v2.0, 2015-02-18, fix [#133](https://github.com/winlinvip/simple-rtmp-server/issues/133), support push rtsp to srs. 2.0.120. * v2.0, 2015-02-17, the join maybe failed, should use a variable to ensure thread terminated. 2.0.119. * v2.0, 2015-02-15, for [#304](https://github.com/winlinvip/simple-rtmp-server/issues/304), support config default acodec/vcodec. 2.0.118. diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 4ef6d6ede..a8a92994b 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -1227,4 +1227,5 @@ vhost removed.srs.com { # config for the pithy print, # which always print constant message specified by interval, # whatever the clients in concurrency. +# default: 10000 pithy_print_ms 10000; diff --git a/trunk/src/app/srs_app_dvr.cpp b/trunk/src/app/srs_app_dvr.cpp index bc7e32624..48c252f32 100644 --- a/trunk/src/app/srs_app_dvr.cpp +++ b/trunk/src/app/srs_app_dvr.cpp @@ -368,11 +368,27 @@ int SrsDvrPlan::flv_open(string stream, string path) int ret = ERROR_SUCCESS; segment->reset(); + + if (srs_path_exists(path)) { + // when path exists, always append to it. + // so we must use the target flv path as output flv. + tmp_flv_file = path; + } else { + // when path not exists, dvr to tmp file. + tmp_flv_file = path + ".tmp"; + } - std::string tmp_file = path + ".tmp"; - if ((ret = fs->open(tmp_file)) != ERROR_SUCCESS) { - srs_error("open file stream for file %s failed. ret=%d", path.c_str(), ret); - return ret; + if (srs_path_exists(path)) { + if ((ret = fs->open_append(tmp_flv_file)) != ERROR_SUCCESS) { + srs_error("append file stream for file %s failed. ret=%d", path.c_str(), ret); + return ret; + } + srs_warn("dvr: always append to when exists, file=%s.", path.c_str()); + } else { + if ((ret = fs->open(tmp_flv_file)) != ERROR_SUCCESS) { + srs_error("open file stream for file %s failed. ret=%d", path.c_str(), ret); + return ret; + } } if ((ret = enc->initialize(fs)) != ERROR_SUCCESS) { @@ -396,12 +412,14 @@ int SrsDvrPlan::flv_close() fs->close(); - std::string tmp_file = segment->path + ".tmp"; - if (rename(tmp_file.c_str(), segment->path.c_str()) < 0) { - ret = ERROR_SYSTEM_FILE_RENAME; - srs_error("rename flv file failed, %s => %s. ret=%d", - tmp_file.c_str(), segment->path.c_str(), ret); - return ret; + // when tmp flv file exists, reap it. + if (tmp_flv_file != segment->path) { + if (rename(tmp_flv_file.c_str(), segment->path.c_str()) < 0) { + ret = ERROR_SYSTEM_FILE_RENAME; + srs_error("rename flv file failed, %s => %s. ret=%d", + tmp_flv_file.c_str(), segment->path.c_str(), ret); + return ret; + } } #ifdef SRS_AUTO_HTTP_CALLBACK diff --git a/trunk/src/app/srs_app_dvr.hpp b/trunk/src/app/srs_app_dvr.hpp index 5ffffa17c..d879c9e0c 100644 --- a/trunk/src/app/srs_app_dvr.hpp +++ b/trunk/src/app/srs_app_dvr.hpp @@ -111,6 +111,8 @@ protected: SrsRequest* _req; bool dvr_enabled; SrsFileWriter* fs; +private: + std::string tmp_flv_file; public: SrsDvrPlan(); virtual ~SrsDvrPlan(); diff --git a/trunk/src/app/srs_app_http.cpp b/trunk/src/app/srs_app_http.cpp index 40981d0fd..9333f7af5 100644 --- a/trunk/src/app/srs_app_http.cpp +++ b/trunk/src/app/srs_app_http.cpp @@ -294,8 +294,7 @@ int SrsGoHttpFileServer::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* } // stat current dir, if exists, return error. - struct stat st; - if (stat(fullpath.c_str(), &st) != 0) { + if (!srs_path_exists(fullpath)) { srs_warn("http miss file=%s, pattern=%s, upath=%s", fullpath.c_str(), entry->pattern.c_str(), upath.c_str()); return SrsGoHttpNotFoundHandler().serve_http(w, r); diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index 75d20939d..96dc21cdd 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 2 #define VERSION_MINOR 0 -#define VERSION_REVISION 121 +#define VERSION_REVISION 122 // server info. #define RTMP_SIG_SRS_KEY "SRS" diff --git a/trunk/src/kernel/srs_kernel_file.cpp b/trunk/src/kernel/srs_kernel_file.cpp index b724ac2a1..f5b08a5b6 100644 --- a/trunk/src/kernel/srs_kernel_file.cpp +++ b/trunk/src/kernel/srs_kernel_file.cpp @@ -69,6 +69,30 @@ int SrsFileWriter::open(string file) return ret; } +int SrsFileWriter::open_append(string file) +{ + int ret = ERROR_SUCCESS; + + if (fd > 0) { + ret = ERROR_SYSTEM_FILE_ALREADY_OPENED; + srs_error("file %s already opened. ret=%d", _file.c_str(), ret); + return ret; + } + + int flags = O_APPEND|O_WRONLY; + mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH; + + if ((fd = ::open(file.c_str(), flags, mode)) < 0) { + ret = ERROR_SYSTEM_FILE_OPENE; + srs_error("open file %s failed. ret=%d", file.c_str(), ret); + return ret; + } + + _file = file; + + return ret; +} + void SrsFileWriter::close() { int ret = ERROR_SUCCESS; diff --git a/trunk/src/kernel/srs_kernel_file.hpp b/trunk/src/kernel/srs_kernel_file.hpp index b870f0128..31857ba13 100644 --- a/trunk/src/kernel/srs_kernel_file.hpp +++ b/trunk/src/kernel/srs_kernel_file.hpp @@ -47,6 +47,10 @@ public: * open file writer, can open then close then open... */ virtual int open(std::string file); + /** + * open file writer in append mode. + */ + virtual int open_append(std::string file); virtual void close(); public: virtual bool is_open(); diff --git a/trunk/src/kernel/srs_kernel_utility.cpp b/trunk/src/kernel/srs_kernel_utility.cpp index 4fc079f35..3a2eeebda 100644 --- a/trunk/src/kernel/srs_kernel_utility.cpp +++ b/trunk/src/kernel/srs_kernel_utility.cpp @@ -230,10 +230,8 @@ int __srs_create_dir_recursively(string dir) { int ret = ERROR_SUCCESS; - struct stat st; - // stat current dir, if exists, return error. - if (stat(dir.c_str(), &st) == 0) { + if (srs_path_exists(dir)) { return ERROR_SYSTEM_DIR_EXISTS; } @@ -279,6 +277,18 @@ int srs_create_dir_recursively(string dir) return ret; } +bool srs_path_exists(std::string path) +{ + struct stat st; + + // stat current dir, if exists, return error. + if (stat(path.c_str(), &st) == 0) { + return true; + } + + return false; +} + bool srs_avc_startswith_annexb(SrsStream* stream, int* pnb_start_code) { char* bytes = stream->data() + stream->pos(); diff --git a/trunk/src/kernel/srs_kernel_utility.hpp b/trunk/src/kernel/srs_kernel_utility.hpp index 0a780c668..d5a514878 100644 --- a/trunk/src/kernel/srs_kernel_utility.hpp +++ b/trunk/src/kernel/srs_kernel_utility.hpp @@ -64,6 +64,9 @@ extern bool srs_string_ends_with(std::string str, std::string flag); // create dir recursively extern int srs_create_dir_recursively(std::string dir); +// whether path exists. +extern bool srs_path_exists(std::string path); + /** * whether stream starts with the avc NALU in "AnnexB" * from H.264-AVC-ISO_IEC_14496-10.pdf, page 211.