winlin

refine the hls deviation for floor algorithm.

@@ -562,6 +562,7 @@ Supported operating systems and hardware: @@ -562,6 +562,7 @@ Supported operating systems and hardware:
562 562
563 ### SRS 2.0 history 563 ### SRS 2.0 history
564 564
  565 +* v2.0, 2015-04-10, refine the hls deviation for floor algorithm.
565 * v2.0, 2015-04-08, for [#375](https://github.com/winlinvip/simple-rtmp-server/issues/375), fix hls bug, keep cc continous between ts files. 2.0.159. 566 * v2.0, 2015-04-08, for [#375](https://github.com/winlinvip/simple-rtmp-server/issues/375), fix hls bug, keep cc continous between ts files. 2.0.159.
566 * v2.0, 2015-04-04, for [#304](https://github.com/winlinvip/simple-rtmp-server/issues/304), rewrite annexb mux for ts, refer to apple sample. 2.0.157. 567 * v2.0, 2015-04-04, for [#304](https://github.com/winlinvip/simple-rtmp-server/issues/304), rewrite annexb mux for ts, refer to apple sample. 2.0.157.
567 * v2.0, 2015-04-03, enhanced avc decode, parse the sps get width+height. 2.0.156. 568 * v2.0, 2015-04-03, enhanced avc decode, parse the sps get width+height. 2.0.156.
@@ -59,10 +59,10 @@ using namespace std; @@ -59,10 +59,10 @@ using namespace std;
59 // drop the segment when duration of ts too small. 59 // drop the segment when duration of ts too small.
60 #define SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS 100 60 #define SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS 100
61 61
62 -// startup piece, the first piece, fragment percent to reap.  
63 -#define SRS_HLS_FLOOR_STARTUP_PERCENT 0.1  
64 // fragment plus the deviation percent. 62 // fragment plus the deviation percent.
65 #define SRS_HLS_FLOOR_REAP_PERCENT 0.2 63 #define SRS_HLS_FLOOR_REAP_PERCENT 0.2
  64 +// reset the piece id when deviation overflow this.
  65 +#define SRS_JUMP_WHEN_PIECE_DEVIATION 10
66 66
67 ISrsHlsHandler::ISrsHlsHandler() 67 ISrsHlsHandler::ISrsHlsHandler()
68 { 68 {
@@ -224,7 +224,7 @@ SrsHlsMuxer::SrsHlsMuxer() @@ -224,7 +224,7 @@ SrsHlsMuxer::SrsHlsMuxer()
224 handler = NULL; 224 handler = NULL;
225 hls_fragment = hls_window = 0; 225 hls_fragment = hls_window = 0;
226 hls_aof_ratio = 1.0; 226 hls_aof_ratio = 1.0;
227 - hls_fragment_deviation = 0; 227 + deviation_ts = 0;
228 hls_cleanup = true; 228 hls_cleanup = true;
229 previous_floor_ts = 0; 229 previous_floor_ts = 0;
230 accept_floor_ts = 0; 230 accept_floor_ts = 0;
@@ -269,26 +269,14 @@ double SrsHlsMuxer::duration() @@ -269,26 +269,14 @@ double SrsHlsMuxer::duration()
269 return current? current->duration:0; 269 return current? current->duration:0;
270 } 270 }
271 271
272 -double SrsHlsMuxer::deviation() 272 +int SrsHlsMuxer::deviation()
273 { 273 {
274 // no floor, no deviation. 274 // no floor, no deviation.
275 if (!hls_ts_floor) { 275 if (!hls_ts_floor) {
276 return 0; 276 return 0;
277 } 277 }
278 278
279 - return hls_fragment_deviation;  
280 -}  
281 -  
282 -int SrsHlsMuxer::absolute_deviation()  
283 -{  
284 - // no floor, no deviation.  
285 - if (!hls_ts_floor) {  
286 - return 0;  
287 - }  
288 -  
289 - // accept the floor ts for the first piece.  
290 - int64_t floor_ts = (int64_t)(srs_get_system_time_ms() / (1000 * hls_fragment));  
291 - return (int)(accept_floor_ts - (floor_ts - 1)); 279 + return deviation_ts;
292 } 280 }
293 281
294 int SrsHlsMuxer::initialize(ISrsHlsHandler* h) 282 int SrsHlsMuxer::initialize(ISrsHlsHandler* h)
@@ -323,9 +311,7 @@ int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix, @@ -323,9 +311,7 @@ int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix,
323 previous_floor_ts = 0; 311 previous_floor_ts = 0;
324 accept_floor_ts = 0; 312 accept_floor_ts = 0;
325 hls_window = window; 313 hls_window = window;
326 - // for the first time, we set to -N% of fragment,  
327 - // that is, the first piece always smaller.  
328 - hls_fragment_deviation = -1 * (fragment * SRS_HLS_FLOOR_STARTUP_PERCENT); 314 + deviation_ts = 0;
329 315
330 // generate the m3u8 dir and path. 316 // generate the m3u8 dir and path.
331 m3u8 = path + "/" + m3u8_file; 317 m3u8 = path + "/" + m3u8_file;
@@ -412,24 +398,33 @@ int SrsHlsMuxer::segment_open(int64_t segment_start_dts) @@ -412,24 +398,33 @@ int SrsHlsMuxer::segment_open(int64_t segment_start_dts)
412 ts_file = srs_path_build_stream(ts_file, req->vhost, req->app, req->stream); 398 ts_file = srs_path_build_stream(ts_file, req->vhost, req->app, req->stream);
413 if (hls_ts_floor) { 399 if (hls_ts_floor) {
414 // accept the floor ts for the first piece. 400 // accept the floor ts for the first piece.
415 - int64_t floor_ts = (int64_t)(srs_get_system_time_ms() / (1000 * hls_fragment)); 401 + int64_t current_floor_ts = (int64_t)(srs_get_system_time_ms() / (1000 * hls_fragment));
416 if (!accept_floor_ts) { 402 if (!accept_floor_ts) {
417 - accept_floor_ts = floor_ts - 1; 403 + accept_floor_ts = current_floor_ts - 1;
418 } else { 404 } else {
419 accept_floor_ts++; 405 accept_floor_ts++;
420 } 406 }
421 407
  408 + // jump when deviation more than 10p
  409 + if (accept_floor_ts - current_floor_ts > SRS_JUMP_WHEN_PIECE_DEVIATION) {
  410 + srs_warn("hls: jmp for ts deviation, current=%"PRId64", accept=%"PRId64, current_floor_ts, accept_floor_ts);
  411 + accept_floor_ts = current_floor_ts - 1;
  412 + }
  413 +
  414 + // when reap ts, adjust the deviation.
  415 + deviation_ts = (int)(accept_floor_ts - current_floor_ts);
  416 +
422 // we always ensure the piece is increase one by one. 417 // we always ensure the piece is increase one by one.
423 std::stringstream ts_floor; 418 std::stringstream ts_floor;
424 ts_floor << accept_floor_ts; 419 ts_floor << accept_floor_ts;
425 ts_file = srs_string_replace(ts_file, "[timestamp]", ts_floor.str()); 420 ts_file = srs_string_replace(ts_file, "[timestamp]", ts_floor.str());
426 421
427 // dup/jmp detect for ts in floor mode. 422 // dup/jmp detect for ts in floor mode.
428 - if (previous_floor_ts && previous_floor_ts != floor_ts - 1) {  
429 - srs_warn("hls: dup or jmp for floor ts, previous=%"PRId64", current=%"PRId64", ts=%s, deviation=%.2f",  
430 - previous_floor_ts, floor_ts, ts_file.c_str(), hls_fragment_deviation); 423 + if (previous_floor_ts && previous_floor_ts != current_floor_ts - 1) {
  424 + srs_warn("hls: dup or jmp for floor ts, previous=%"PRId64", current=%"PRId64", accept=%"PRId64", deviation=%d",
  425 + previous_floor_ts, current_floor_ts, accept_floor_ts, deviation_ts);
431 } 426 }
432 - previous_floor_ts = floor_ts; 427 + previous_floor_ts = current_floor_ts;
433 } 428 }
434 ts_file = srs_path_build_timestamp(ts_file); 429 ts_file = srs_path_build_timestamp(ts_file);
435 if (true) { 430 if (true) {
@@ -497,7 +492,7 @@ bool SrsHlsMuxer::is_segment_overflow() @@ -497,7 +492,7 @@ bool SrsHlsMuxer::is_segment_overflow()
497 srs_assert(current); 492 srs_assert(current);
498 493
499 // use N% deviation, to smoother. 494 // use N% deviation, to smoother.
500 - double deviation = hls_ts_floor? SRS_HLS_FLOOR_REAP_PERCENT * hls_fragment_deviation : 0.0; 495 + double deviation = hls_ts_floor? SRS_HLS_FLOOR_REAP_PERCENT * deviation_ts * hls_fragment : 0.0;
501 496
502 return current->duration >= hls_fragment + deviation; 497 return current->duration >= hls_fragment + deviation;
503 } 498 }
@@ -594,19 +589,14 @@ int SrsHlsMuxer::segment_close(string log_desc) @@ -594,19 +589,14 @@ int SrsHlsMuxer::segment_close(string log_desc)
594 if (current->duration * 1000 >= SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS) { 589 if (current->duration * 1000 >= SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS) {
595 segments.push_back(current); 590 segments.push_back(current);
596 591
597 - // when reap ts, adjust the deviation.  
598 - if (hls_ts_floor) {  
599 - hls_fragment_deviation += (double)(hls_fragment - current->duration);  
600 - }  
601 -  
602 // use async to call the http hooks, for it will cause thread switch. 592 // use async to call the http hooks, for it will cause thread switch.
603 if ((ret = async->call(new SrsDvrAsyncCallOnHls(req, current->full_path, current->sequence_no, current->duration))) != ERROR_SUCCESS) { 593 if ((ret = async->call(new SrsDvrAsyncCallOnHls(req, current->full_path, current->sequence_no, current->duration))) != ERROR_SUCCESS) {
604 return ret; 594 return ret;
605 } 595 }
606 596
607 - srs_info("%s reap ts segment, sequence_no=%d, uri=%s, duration=%.2f, start=%"PRId64", deviation=%.2f", 597 + srs_info("%s reap ts segment, sequence_no=%d, uri=%s, duration=%.2f, start=%"PRId64,
608 log_desc.c_str(), current->sequence_no, current->uri.c_str(), current->duration, 598 log_desc.c_str(), current->sequence_no, current->uri.c_str(), current->duration,
609 - current->segment_start_dts, hls_fragment_deviation); 599 + current->segment_start_dts);
610 600
611 // notify handler for update ts. 601 // notify handler for update ts.
612 srs_assert(current->writer); 602 srs_assert(current->writer);
@@ -1222,9 +1212,9 @@ void SrsHls::hls_show_mux_log() @@ -1222,9 +1212,9 @@ void SrsHls::hls_show_mux_log()
1222 // the run time is not equals to stream time, 1212 // the run time is not equals to stream time,
1223 // @see: https://github.com/winlinvip/simple-rtmp-server/issues/81#issuecomment-48100994 1213 // @see: https://github.com/winlinvip/simple-rtmp-server/issues/81#issuecomment-48100994
1224 // it's ok. 1214 // it's ok.
1225 - srs_trace("-> "SRS_CONSTS_LOG_HLS" time=%"PRId64", stream dts=%"PRId64"(%"PRId64"ms), sno=%d, ts=%s, dur=%.2f, dva=%.2fs/%dp", 1215 + srs_trace("-> "SRS_CONSTS_LOG_HLS" time=%"PRId64", stream dts=%"PRId64"(%"PRId64"ms), sno=%d, ts=%s, dur=%.2f, dva=%dp",
1226 pprint->age(), stream_dts, stream_dts / 90, muxer->sequence_no(), muxer->ts_url().c_str(), 1216 pprint->age(), stream_dts, stream_dts / 90, muxer->sequence_no(), muxer->ts_url().c_str(),
1227 - muxer->duration(), muxer->deviation(), muxer->absolute_deviation()); 1217 + muxer->duration(), muxer->deviation());
1228 } 1218 }
1229 } 1219 }
1230 1220
@@ -199,9 +199,9 @@ private: @@ -199,9 +199,9 @@ private:
199 private: 199 private:
200 // whether use floor algorithm for timestamp. 200 // whether use floor algorithm for timestamp.
201 bool hls_ts_floor; 201 bool hls_ts_floor;
202 - // the deviation in seconds to adjust the fragment to be more 202 + // the deviation in piece to adjust the fragment to be more
203 // bigger or smaller. 203 // bigger or smaller.
204 - double hls_fragment_deviation; 204 + int deviation_ts;
205 // the previous reap floor timestamp, 205 // the previous reap floor timestamp,
206 // used to detect the dup or jmp or ts. 206 // used to detect the dup or jmp or ts.
207 int64_t accept_floor_ts; 207 int64_t accept_floor_ts;
@@ -242,8 +242,7 @@ public: @@ -242,8 +242,7 @@ public:
242 virtual int sequence_no(); 242 virtual int sequence_no();
243 virtual std::string ts_url(); 243 virtual std::string ts_url();
244 virtual double duration(); 244 virtual double duration();
245 - virtual double deviation();  
246 - virtual int absolute_deviation(); 245 + virtual int deviation();
247 public: 246 public:
248 /** 247 /**
249 * initialize the hls muxer. 248 * initialize the hls muxer.