winlin

add utc time format.

@@ -44,6 +44,11 @@ max_connections 1000; @@ -44,6 +44,11 @@ max_connections 1000;
44 # @remark: donot support reload. 44 # @remark: donot support reload.
45 # default: on 45 # default: on
46 daemon on; 46 daemon on;
  47 +# whether use utc_time to generate the time struct,
  48 +# if off, use localtime() to generate it,
  49 +# if on, use gmtime() instead, which use UTC time.
  50 +# default: off
  51 +utc_time off;
47 52
48 ############################################################################################# 53 #############################################################################################
49 # heartbeat/stats sections 54 # heartbeat/stats sections
@@ -1336,7 +1336,8 @@ int SrsConfig::check_config() @@ -1336,7 +1336,8 @@ int SrsConfig::check_config()
1336 && n != "srs_log_tank" && n != "srs_log_level" && n != "srs_log_file" 1336 && n != "srs_log_tank" && n != "srs_log_level" && n != "srs_log_file"
1337 && n != "max_connections" && n != "daemon" && n != "heartbeat" 1337 && n != "max_connections" && n != "daemon" && n != "heartbeat"
1338 && n != "http_api" && n != "stats" && n != "vhost" && n != "pithy_print_ms" 1338 && n != "http_api" && n != "stats" && n != "vhost" && n != "pithy_print_ms"
1339 - && n != "http_stream" && n != "http_server" && n != "stream_caster") 1339 + && n != "http_stream" && n != "http_server" && n != "stream_caster"
  1340 + && n != "utc_time")
1340 { 1341 {
1341 ret = ERROR_SYSTEM_CONFIG_INVALID; 1342 ret = ERROR_SYSTEM_CONFIG_INVALID;
1342 srs_error("unsupported directive %s, ret=%d", n.c_str(), ret); 1343 srs_error("unsupported directive %s, ret=%d", n.c_str(), ret);
@@ -1896,6 +1897,16 @@ int SrsConfig::get_pithy_print_ms() @@ -1896,6 +1897,16 @@ int SrsConfig::get_pithy_print_ms()
1896 return ::atoi(pithy->arg0().c_str()); 1897 return ::atoi(pithy->arg0().c_str());
1897 } 1898 }
1898 1899
  1900 +bool SrsConfig::get_utc_time()
  1901 +{
  1902 + SrsConfDirective* utc = root->get("utc_time");
  1903 + if (!utc || utc->arg0().empty()) {
  1904 + return SRS_CONF_DEFAULT_UTC_TIME;
  1905 + }
  1906 +
  1907 + return utc->arg0() == "on";
  1908 +}
  1909 +
1899 vector<SrsConfDirective*> SrsConfig::get_stream_casters() 1910 vector<SrsConfDirective*> SrsConfig::get_stream_casters()
1900 { 1911 {
1901 srs_assert(root); 1912 srs_assert(root);
@@ -43,6 +43,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -43,6 +43,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
43 #define SRS_CONF_DEFAULT_LOG_TANK_CONSOLE "console" 43 #define SRS_CONF_DEFAULT_LOG_TANK_CONSOLE "console"
44 #define SRS_CONF_DEFAULT_COFNIG_FILE "conf/srs.conf" 44 #define SRS_CONF_DEFAULT_COFNIG_FILE "conf/srs.conf"
45 #define SRS_CONF_DEFAULT_FF_LOG_DIR "./objs" 45 #define SRS_CONF_DEFAULT_FF_LOG_DIR "./objs"
  46 +#define SRS_CONF_DEFAULT_UTC_TIME false
46 47
47 #define SRS_CONF_DEFAULT_MAX_CONNECTIONS 1000 48 #define SRS_CONF_DEFAULT_MAX_CONNECTIONS 1000
48 #define SRS_CONF_DEFAULT_HLS_PATH "./objs/nginx/html" 49 #define SRS_CONF_DEFAULT_HLS_PATH "./objs/nginx/html"
@@ -435,6 +436,10 @@ public: @@ -435,6 +436,10 @@ public:
435 * every this interval in ms. 436 * every this interval in ms.
436 */ 437 */
437 virtual int get_pithy_print_ms(); 438 virtual int get_pithy_print_ms();
  439 + /**
  440 + * whether use utc-time to format the time.
  441 + */
  442 + virtual bool get_utc_time();
438 // stream_caster section 443 // stream_caster section
439 public: 444 public:
440 /** 445 /**
@@ -311,12 +311,6 @@ int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix, @@ -311,12 +311,6 @@ int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix,
311 // generate the m3u8 dir and path. 311 // generate the m3u8 dir and path.
312 m3u8 = path + "/" + m3u8_file; 312 m3u8 = path + "/" + m3u8_file;
313 m3u8 = srs_path_build_stream(m3u8, req->vhost, req->app, req->stream); 313 m3u8 = srs_path_build_stream(m3u8, req->vhost, req->app, req->stream);
314 -  
315 - m3u8_dir = m3u8;  
316 - size_t pos = string::npos;  
317 - if ((pos = m3u8_dir.rfind("/")) != string::npos) {  
318 - m3u8_dir = m3u8_dir.substr(0, pos);  
319 - }  
320 314
321 // we always keep the target duration increasing. 315 // we always keep the target duration increasing.
322 int max_td = srs_max(target_duration, (int)(fragment * _srs_config->get_hls_td_ratio(r->vhost))); 316 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, @@ -336,6 +330,14 @@ int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix,
336 should_write_file = true; 330 should_write_file = true;
337 } 331 }
338 332
  333 + // create m3u8 dir once.
  334 + m3u8_dir = srs_path_dirname(m3u8);
  335 + if (should_write_file && (ret = srs_create_dir_recursively(m3u8_dir)) != ERROR_SUCCESS) {
  336 + srs_error("create app dir %s failed. ret=%d", m3u8_dir.c_str(), ret);
  337 + return ret;
  338 + }
  339 + srs_info("create m3u8 dir %s ok", m3u8_dir.c_str());
  340 +
339 return ret; 341 return ret;
340 } 342 }
341 343
@@ -434,11 +436,12 @@ int SrsHlsMuxer::segment_open(int64_t segment_start_dts) @@ -434,11 +436,12 @@ int SrsHlsMuxer::segment_open(int64_t segment_start_dts)
434 current->uri += ts_url; 436 current->uri += ts_url;
435 437
436 // create dir recursively for hls. 438 // create dir recursively for hls.
437 - if (should_write_file && (ret = srs_create_dir_recursively(m3u8_dir)) != ERROR_SUCCESS) {  
438 - srs_error("create app dir %s failed. ret=%d", m3u8_dir.c_str(), ret); 439 + std::string ts_dir = srs_path_dirname(current->full_path);
  440 + if (should_write_file && (ret = srs_create_dir_recursively(ts_dir)) != ERROR_SUCCESS) {
  441 + srs_error("create app dir %s failed. ret=%d", ts_dir.c_str(), ret);
439 return ret; 442 return ret;
440 } 443 }
441 - srs_info("create app dir %s ok", m3u8_dir.c_str()); 444 + srs_info("create ts dir %s ok", ts_dir.c_str());
442 445
443 // open temp ts file. 446 // open temp ts file.
444 std::string tmp_file = current->full_path + ".tmp"; 447 std::string tmp_file = current->full_path + ".tmp";
@@ -274,8 +274,14 @@ bool SrsFastLog::generate_header(bool error, const char* tag, int context_id, co @@ -274,8 +274,14 @@ bool SrsFastLog::generate_header(bool error, const char* tag, int context_id, co
274 274
275 // to calendar time 275 // to calendar time
276 struct tm* tm; 276 struct tm* tm;
277 - if ((tm = localtime(&tv.tv_sec)) == NULL) {  
278 - return false; 277 + if (_srs_config->get_utc_time()) {
  278 + if ((tm = gmtime(&tv.tv_sec)) == NULL) {
  279 + return false;
  280 + }
  281 + } else {
  282 + if ((tm = localtime(&tv.tv_sec)) == NULL) {
  283 + return false;
  284 + }
279 } 285 }
280 286
281 // write log header 287 // write log header
@@ -140,8 +140,14 @@ string srs_path_build_timestamp(string template_path) @@ -140,8 +140,14 @@ string srs_path_build_timestamp(string template_path)
140 140
141 // to calendar time 141 // to calendar time
142 struct tm* tm; 142 struct tm* tm;
143 - if ((tm = localtime(&tv.tv_sec)) == NULL) {  
144 - return path; 143 + if (_srs_config->get_utc_time()) {
  144 + if ((tm = gmtime(&tv.tv_sec)) == NULL) {
  145 + return path;
  146 + }
  147 + } else {
  148 + if ((tm = localtime(&tv.tv_sec)) == NULL) {
  149 + return path;
  150 + }
145 } 151 }
146 152
147 // the buffer to format the date and time. 153 // the buffer to format the date and time.
@@ -154,32 +160,32 @@ string srs_path_build_timestamp(string template_path) @@ -154,32 +160,32 @@ string srs_path_build_timestamp(string template_path)
154 } 160 }
155 // [2006], replace with current year. 161 // [2006], replace with current year.
156 if (true) { 162 if (true) {
157 - snprintf(buf, sizeof(buf), "%d", 1900 + tm->tm_year); 163 + snprintf(buf, sizeof(buf), "%04d", 1900 + tm->tm_year);
158 path = srs_string_replace(path, "[2006]", buf); 164 path = srs_string_replace(path, "[2006]", buf);
159 } 165 }
160 // [01], replace this const to current month. 166 // [01], replace this const to current month.
161 if (true) { 167 if (true) {
162 - snprintf(buf, sizeof(buf), "%d", 1 + tm->tm_mon); 168 + snprintf(buf, sizeof(buf), "%02d", 1 + tm->tm_mon);
163 path = srs_string_replace(path, "[01]", buf); 169 path = srs_string_replace(path, "[01]", buf);
164 } 170 }
165 // [02], replace this const to current date. 171 // [02], replace this const to current date.
166 if (true) { 172 if (true) {
167 - snprintf(buf, sizeof(buf), "%d", tm->tm_mday); 173 + snprintf(buf, sizeof(buf), "%02d", tm->tm_mday);
168 path = srs_string_replace(path, "[02]", buf); 174 path = srs_string_replace(path, "[02]", buf);
169 } 175 }
170 // [15], replace this const to current hour. 176 // [15], replace this const to current hour.
171 if (true) { 177 if (true) {
172 - snprintf(buf, sizeof(buf), "%d", tm->tm_hour); 178 + snprintf(buf, sizeof(buf), "%02d", tm->tm_hour);
173 path = srs_string_replace(path, "[15]", buf); 179 path = srs_string_replace(path, "[15]", buf);
174 } 180 }
175 // [04], repleace this const to current minute. 181 // [04], repleace this const to current minute.
176 if (true) { 182 if (true) {
177 - snprintf(buf, sizeof(buf), "%d", tm->tm_min); 183 + snprintf(buf, sizeof(buf), "%02d", tm->tm_min);
178 path = srs_string_replace(path, "[04]", buf); 184 path = srs_string_replace(path, "[04]", buf);
179 } 185 }
180 // [05], repleace this const to current second. 186 // [05], repleace this const to current second.
181 if (true) { 187 if (true) {
182 - snprintf(buf, sizeof(buf), "%d", tm->tm_sec); 188 + snprintf(buf, sizeof(buf), "%02d", tm->tm_sec);
183 path = srs_string_replace(path, "[05]", buf); 189 path = srs_string_replace(path, "[05]", buf);
184 } 190 }
185 // [999], repleace this const to current millisecond. 191 // [999], repleace this const to current millisecond.
@@ -294,6 +294,21 @@ bool srs_path_exists(std::string path) @@ -294,6 +294,21 @@ bool srs_path_exists(std::string path)
294 return false; 294 return false;
295 } 295 }
296 296
  297 +string srs_path_dirname(string path)
  298 +{
  299 + std::string dirname = path;
  300 + size_t pos = string::npos;
  301 +
  302 + if ((pos = dirname.rfind("/")) != string::npos) {
  303 + if (pos == 0) {
  304 + return "/";
  305 + }
  306 + dirname = dirname.substr(0, pos);
  307 + }
  308 +
  309 + return dirname;
  310 +}
  311 +
297 bool srs_avc_startswith_annexb(SrsStream* stream, int* pnb_start_code) 312 bool srs_avc_startswith_annexb(SrsStream* stream, int* pnb_start_code)
298 { 313 {
299 char* bytes = stream->data() + stream->pos(); 314 char* bytes = stream->data() + stream->pos();
@@ -68,6 +68,8 @@ extern int srs_create_dir_recursively(std::string dir); @@ -68,6 +68,8 @@ extern int srs_create_dir_recursively(std::string dir);
68 68
69 // whether path exists. 69 // whether path exists.
70 extern bool srs_path_exists(std::string path); 70 extern bool srs_path_exists(std::string path);
  71 +// get the dirname of path
  72 +extern std::string srs_path_dirname(std::string path);
71 73
72 /** 74 /**
73 * whether stream starts with the avc NALU in "AnnexB" 75 * whether stream starts with the avc NALU in "AnnexB"