diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 9d106768a..491250669 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -44,6 +44,11 @@ max_connections 1000; # @remark: donot support reload. # default: on daemon on; +# whether use utc_time to generate the time struct, +# if off, use localtime() to generate it, +# if on, use gmtime() instead, which use UTC time. +# default: off +utc_time off; ############################################################################################# # heartbeat/stats sections diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 96c84fdcf..8193a3be2 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -1336,7 +1336,8 @@ int SrsConfig::check_config() && n != "srs_log_tank" && n != "srs_log_level" && n != "srs_log_file" && n != "max_connections" && n != "daemon" && n != "heartbeat" && n != "http_api" && n != "stats" && n != "vhost" && n != "pithy_print_ms" - && n != "http_stream" && n != "http_server" && n != "stream_caster") + && n != "http_stream" && n != "http_server" && n != "stream_caster" + && n != "utc_time") { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported directive %s, ret=%d", n.c_str(), ret); @@ -1896,6 +1897,16 @@ int SrsConfig::get_pithy_print_ms() return ::atoi(pithy->arg0().c_str()); } +bool SrsConfig::get_utc_time() +{ + SrsConfDirective* utc = root->get("utc_time"); + if (!utc || utc->arg0().empty()) { + return SRS_CONF_DEFAULT_UTC_TIME; + } + + return utc->arg0() == "on"; +} + vector SrsConfig::get_stream_casters() { srs_assert(root); diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 1df56679d..025e6e005 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -43,6 +43,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define SRS_CONF_DEFAULT_LOG_TANK_CONSOLE "console" #define SRS_CONF_DEFAULT_COFNIG_FILE "conf/srs.conf" #define SRS_CONF_DEFAULT_FF_LOG_DIR "./objs" +#define SRS_CONF_DEFAULT_UTC_TIME false #define SRS_CONF_DEFAULT_MAX_CONNECTIONS 1000 #define SRS_CONF_DEFAULT_HLS_PATH "./objs/nginx/html" @@ -435,6 +436,10 @@ public: * every this interval in ms. */ virtual int get_pithy_print_ms(); + /** + * whether use utc-time to format the time. + */ + virtual bool get_utc_time(); // stream_caster section public: /** diff --git a/trunk/src/app/srs_app_hls.cpp b/trunk/src/app/srs_app_hls.cpp index 8a8b1a237..73ee2e3bb 100644 --- a/trunk/src/app/srs_app_hls.cpp +++ b/trunk/src/app/srs_app_hls.cpp @@ -311,12 +311,6 @@ int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix, // generate the m3u8 dir and path. m3u8 = path + "/" + m3u8_file; m3u8 = srs_path_build_stream(m3u8, req->vhost, req->app, req->stream); - - m3u8_dir = m3u8; - size_t pos = string::npos; - if ((pos = m3u8_dir.rfind("/")) != string::npos) { - m3u8_dir = m3u8_dir.substr(0, pos); - } // we always keep the target duration increasing. int max_td = srs_max(target_duration, (int)(fragment * _srs_config->get_hls_td_ratio(r->vhost))); @@ -336,6 +330,14 @@ int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix, should_write_file = true; } + // create m3u8 dir once. + m3u8_dir = srs_path_dirname(m3u8); + if (should_write_file && (ret = srs_create_dir_recursively(m3u8_dir)) != ERROR_SUCCESS) { + srs_error("create app dir %s failed. ret=%d", m3u8_dir.c_str(), ret); + return ret; + } + srs_info("create m3u8 dir %s ok", m3u8_dir.c_str()); + return ret; } @@ -434,11 +436,12 @@ int SrsHlsMuxer::segment_open(int64_t segment_start_dts) current->uri += ts_url; // create dir recursively for hls. - if (should_write_file && (ret = srs_create_dir_recursively(m3u8_dir)) != ERROR_SUCCESS) { - srs_error("create app dir %s failed. ret=%d", m3u8_dir.c_str(), ret); + std::string ts_dir = srs_path_dirname(current->full_path); + if (should_write_file && (ret = srs_create_dir_recursively(ts_dir)) != ERROR_SUCCESS) { + srs_error("create app dir %s failed. ret=%d", ts_dir.c_str(), ret); return ret; } - srs_info("create app dir %s ok", m3u8_dir.c_str()); + srs_info("create ts dir %s ok", ts_dir.c_str()); // open temp ts file. std::string tmp_file = current->full_path + ".tmp"; diff --git a/trunk/src/app/srs_app_log.cpp b/trunk/src/app/srs_app_log.cpp index cbd4a3368..798450213 100644 --- a/trunk/src/app/srs_app_log.cpp +++ b/trunk/src/app/srs_app_log.cpp @@ -274,8 +274,14 @@ bool SrsFastLog::generate_header(bool error, const char* tag, int context_id, co // to calendar time struct tm* tm; - if ((tm = localtime(&tv.tv_sec)) == NULL) { - return false; + if (_srs_config->get_utc_time()) { + if ((tm = gmtime(&tv.tv_sec)) == NULL) { + return false; + } + } else { + if ((tm = localtime(&tv.tv_sec)) == NULL) { + return false; + } } // write log header diff --git a/trunk/src/app/srs_app_utility.cpp b/trunk/src/app/srs_app_utility.cpp index 9e93a4601..854656891 100644 --- a/trunk/src/app/srs_app_utility.cpp +++ b/trunk/src/app/srs_app_utility.cpp @@ -140,8 +140,14 @@ string srs_path_build_timestamp(string template_path) // to calendar time struct tm* tm; - if ((tm = localtime(&tv.tv_sec)) == NULL) { - return path; + if (_srs_config->get_utc_time()) { + if ((tm = gmtime(&tv.tv_sec)) == NULL) { + return path; + } + } else { + if ((tm = localtime(&tv.tv_sec)) == NULL) { + return path; + } } // the buffer to format the date and time. @@ -154,32 +160,32 @@ string srs_path_build_timestamp(string template_path) } // [2006], replace with current year. if (true) { - snprintf(buf, sizeof(buf), "%d", 1900 + tm->tm_year); + snprintf(buf, sizeof(buf), "%04d", 1900 + tm->tm_year); path = srs_string_replace(path, "[2006]", buf); } // [01], replace this const to current month. if (true) { - snprintf(buf, sizeof(buf), "%d", 1 + tm->tm_mon); + snprintf(buf, sizeof(buf), "%02d", 1 + tm->tm_mon); path = srs_string_replace(path, "[01]", buf); } // [02], replace this const to current date. if (true) { - snprintf(buf, sizeof(buf), "%d", tm->tm_mday); + snprintf(buf, sizeof(buf), "%02d", tm->tm_mday); path = srs_string_replace(path, "[02]", buf); } // [15], replace this const to current hour. if (true) { - snprintf(buf, sizeof(buf), "%d", tm->tm_hour); + snprintf(buf, sizeof(buf), "%02d", tm->tm_hour); path = srs_string_replace(path, "[15]", buf); } // [04], repleace this const to current minute. if (true) { - snprintf(buf, sizeof(buf), "%d", tm->tm_min); + snprintf(buf, sizeof(buf), "%02d", tm->tm_min); path = srs_string_replace(path, "[04]", buf); } // [05], repleace this const to current second. if (true) { - snprintf(buf, sizeof(buf), "%d", tm->tm_sec); + snprintf(buf, sizeof(buf), "%02d", tm->tm_sec); path = srs_string_replace(path, "[05]", buf); } // [999], repleace this const to current millisecond. diff --git a/trunk/src/kernel/srs_kernel_utility.cpp b/trunk/src/kernel/srs_kernel_utility.cpp index 82061b60c..218ac401d 100644 --- a/trunk/src/kernel/srs_kernel_utility.cpp +++ b/trunk/src/kernel/srs_kernel_utility.cpp @@ -294,6 +294,21 @@ bool srs_path_exists(std::string path) return false; } +string srs_path_dirname(string path) +{ + std::string dirname = path; + size_t pos = string::npos; + + if ((pos = dirname.rfind("/")) != string::npos) { + if (pos == 0) { + return "/"; + } + dirname = dirname.substr(0, pos); + } + + return dirname; +} + 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 5269703fe..7317759cc 100644 --- a/trunk/src/kernel/srs_kernel_utility.hpp +++ b/trunk/src/kernel/srs_kernel_utility.hpp @@ -68,6 +68,8 @@ extern int srs_create_dir_recursively(std::string dir); // whether path exists. extern bool srs_path_exists(std::string path); +// get the dirname of path +extern std::string srs_path_dirname(std::string path); /** * whether stream starts with the avc NALU in "AnnexB"