mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
refine the hls deviation for floor algorithm.
This commit is contained in:
parent
23b310971e
commit
7dbc95e085
3 changed files with 30 additions and 40 deletions
|
@ -562,6 +562,7 @@ Supported operating systems and hardware:
|
||||||
|
|
||||||
### SRS 2.0 history
|
### SRS 2.0 history
|
||||||
|
|
||||||
|
* v2.0, 2015-04-10, refine the hls deviation for floor algorithm.
|
||||||
* 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.
|
* 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.
|
||||||
* 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.
|
* 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.
|
||||||
* v2.0, 2015-04-03, enhanced avc decode, parse the sps get width+height. 2.0.156.
|
* v2.0, 2015-04-03, enhanced avc decode, parse the sps get width+height. 2.0.156.
|
||||||
|
|
|
@ -59,10 +59,10 @@ using namespace std;
|
||||||
// drop the segment when duration of ts too small.
|
// drop the segment when duration of ts too small.
|
||||||
#define SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS 100
|
#define SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS 100
|
||||||
|
|
||||||
// startup piece, the first piece, fragment percent to reap.
|
|
||||||
#define SRS_HLS_FLOOR_STARTUP_PERCENT 0.1
|
|
||||||
// fragment plus the deviation percent.
|
// fragment plus the deviation percent.
|
||||||
#define SRS_HLS_FLOOR_REAP_PERCENT 0.2
|
#define SRS_HLS_FLOOR_REAP_PERCENT 0.2
|
||||||
|
// reset the piece id when deviation overflow this.
|
||||||
|
#define SRS_JUMP_WHEN_PIECE_DEVIATION 10
|
||||||
|
|
||||||
ISrsHlsHandler::ISrsHlsHandler()
|
ISrsHlsHandler::ISrsHlsHandler()
|
||||||
{
|
{
|
||||||
|
@ -224,7 +224,7 @@ SrsHlsMuxer::SrsHlsMuxer()
|
||||||
handler = NULL;
|
handler = NULL;
|
||||||
hls_fragment = hls_window = 0;
|
hls_fragment = hls_window = 0;
|
||||||
hls_aof_ratio = 1.0;
|
hls_aof_ratio = 1.0;
|
||||||
hls_fragment_deviation = 0;
|
deviation_ts = 0;
|
||||||
hls_cleanup = true;
|
hls_cleanup = true;
|
||||||
previous_floor_ts = 0;
|
previous_floor_ts = 0;
|
||||||
accept_floor_ts = 0;
|
accept_floor_ts = 0;
|
||||||
|
@ -269,26 +269,14 @@ double SrsHlsMuxer::duration()
|
||||||
return current? current->duration:0;
|
return current? current->duration:0;
|
||||||
}
|
}
|
||||||
|
|
||||||
double SrsHlsMuxer::deviation()
|
int SrsHlsMuxer::deviation()
|
||||||
{
|
{
|
||||||
// no floor, no deviation.
|
// no floor, no deviation.
|
||||||
if (!hls_ts_floor) {
|
if (!hls_ts_floor) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return hls_fragment_deviation;
|
return deviation_ts;
|
||||||
}
|
|
||||||
|
|
||||||
int SrsHlsMuxer::absolute_deviation()
|
|
||||||
{
|
|
||||||
// no floor, no deviation.
|
|
||||||
if (!hls_ts_floor) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// accept the floor ts for the first piece.
|
|
||||||
int64_t floor_ts = (int64_t)(srs_get_system_time_ms() / (1000 * hls_fragment));
|
|
||||||
return (int)(accept_floor_ts - (floor_ts - 1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsHlsMuxer::initialize(ISrsHlsHandler* h)
|
int SrsHlsMuxer::initialize(ISrsHlsHandler* h)
|
||||||
|
@ -323,9 +311,7 @@ int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix,
|
||||||
previous_floor_ts = 0;
|
previous_floor_ts = 0;
|
||||||
accept_floor_ts = 0;
|
accept_floor_ts = 0;
|
||||||
hls_window = window;
|
hls_window = window;
|
||||||
// for the first time, we set to -N% of fragment,
|
deviation_ts = 0;
|
||||||
// that is, the first piece always smaller.
|
|
||||||
hls_fragment_deviation = -1 * (fragment * SRS_HLS_FLOOR_STARTUP_PERCENT);
|
|
||||||
|
|
||||||
// generate the m3u8 dir and path.
|
// generate the m3u8 dir and path.
|
||||||
m3u8 = path + "/" + m3u8_file;
|
m3u8 = path + "/" + m3u8_file;
|
||||||
|
@ -412,24 +398,33 @@ int SrsHlsMuxer::segment_open(int64_t segment_start_dts)
|
||||||
ts_file = srs_path_build_stream(ts_file, req->vhost, req->app, req->stream);
|
ts_file = srs_path_build_stream(ts_file, req->vhost, req->app, req->stream);
|
||||||
if (hls_ts_floor) {
|
if (hls_ts_floor) {
|
||||||
// accept the floor ts for the first piece.
|
// accept the floor ts for the first piece.
|
||||||
int64_t floor_ts = (int64_t)(srs_get_system_time_ms() / (1000 * hls_fragment));
|
int64_t current_floor_ts = (int64_t)(srs_get_system_time_ms() / (1000 * hls_fragment));
|
||||||
if (!accept_floor_ts) {
|
if (!accept_floor_ts) {
|
||||||
accept_floor_ts = floor_ts - 1;
|
accept_floor_ts = current_floor_ts - 1;
|
||||||
} else {
|
} else {
|
||||||
accept_floor_ts++;
|
accept_floor_ts++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// jump when deviation more than 10p
|
||||||
|
if (accept_floor_ts - current_floor_ts > SRS_JUMP_WHEN_PIECE_DEVIATION) {
|
||||||
|
srs_warn("hls: jmp for ts deviation, current=%"PRId64", accept=%"PRId64, current_floor_ts, accept_floor_ts);
|
||||||
|
accept_floor_ts = current_floor_ts - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// when reap ts, adjust the deviation.
|
||||||
|
deviation_ts = (int)(accept_floor_ts - current_floor_ts);
|
||||||
|
|
||||||
// we always ensure the piece is increase one by one.
|
// we always ensure the piece is increase one by one.
|
||||||
std::stringstream ts_floor;
|
std::stringstream ts_floor;
|
||||||
ts_floor << accept_floor_ts;
|
ts_floor << accept_floor_ts;
|
||||||
ts_file = srs_string_replace(ts_file, "[timestamp]", ts_floor.str());
|
ts_file = srs_string_replace(ts_file, "[timestamp]", ts_floor.str());
|
||||||
|
|
||||||
// dup/jmp detect for ts in floor mode.
|
// dup/jmp detect for ts in floor mode.
|
||||||
if (previous_floor_ts && previous_floor_ts != floor_ts - 1) {
|
if (previous_floor_ts && previous_floor_ts != current_floor_ts - 1) {
|
||||||
srs_warn("hls: dup or jmp for floor ts, previous=%"PRId64", current=%"PRId64", ts=%s, deviation=%.2f",
|
srs_warn("hls: dup or jmp for floor ts, previous=%"PRId64", current=%"PRId64", accept=%"PRId64", deviation=%d",
|
||||||
previous_floor_ts, floor_ts, ts_file.c_str(), hls_fragment_deviation);
|
previous_floor_ts, current_floor_ts, accept_floor_ts, deviation_ts);
|
||||||
}
|
}
|
||||||
previous_floor_ts = floor_ts;
|
previous_floor_ts = current_floor_ts;
|
||||||
}
|
}
|
||||||
ts_file = srs_path_build_timestamp(ts_file);
|
ts_file = srs_path_build_timestamp(ts_file);
|
||||||
if (true) {
|
if (true) {
|
||||||
|
@ -497,7 +492,7 @@ bool SrsHlsMuxer::is_segment_overflow()
|
||||||
srs_assert(current);
|
srs_assert(current);
|
||||||
|
|
||||||
// use N% deviation, to smoother.
|
// use N% deviation, to smoother.
|
||||||
double deviation = hls_ts_floor? SRS_HLS_FLOOR_REAP_PERCENT * hls_fragment_deviation : 0.0;
|
double deviation = hls_ts_floor? SRS_HLS_FLOOR_REAP_PERCENT * deviation_ts * hls_fragment : 0.0;
|
||||||
|
|
||||||
return current->duration >= hls_fragment + deviation;
|
return current->duration >= hls_fragment + deviation;
|
||||||
}
|
}
|
||||||
|
@ -594,19 +589,14 @@ int SrsHlsMuxer::segment_close(string log_desc)
|
||||||
if (current->duration * 1000 >= SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS) {
|
if (current->duration * 1000 >= SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS) {
|
||||||
segments.push_back(current);
|
segments.push_back(current);
|
||||||
|
|
||||||
// when reap ts, adjust the deviation.
|
|
||||||
if (hls_ts_floor) {
|
|
||||||
hls_fragment_deviation += (double)(hls_fragment - current->duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
// use async to call the http hooks, for it will cause thread switch.
|
// use async to call the http hooks, for it will cause thread switch.
|
||||||
if ((ret = async->call(new SrsDvrAsyncCallOnHls(req, current->full_path, current->sequence_no, current->duration))) != ERROR_SUCCESS) {
|
if ((ret = async->call(new SrsDvrAsyncCallOnHls(req, current->full_path, current->sequence_no, current->duration))) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_info("%s reap ts segment, sequence_no=%d, uri=%s, duration=%.2f, start=%"PRId64", deviation=%.2f",
|
srs_info("%s reap ts segment, sequence_no=%d, uri=%s, duration=%.2f, start=%"PRId64,
|
||||||
log_desc.c_str(), current->sequence_no, current->uri.c_str(), current->duration,
|
log_desc.c_str(), current->sequence_no, current->uri.c_str(), current->duration,
|
||||||
current->segment_start_dts, hls_fragment_deviation);
|
current->segment_start_dts);
|
||||||
|
|
||||||
// notify handler for update ts.
|
// notify handler for update ts.
|
||||||
srs_assert(current->writer);
|
srs_assert(current->writer);
|
||||||
|
@ -1222,9 +1212,9 @@ void SrsHls::hls_show_mux_log()
|
||||||
// the run time is not equals to stream time,
|
// the run time is not equals to stream time,
|
||||||
// @see: https://github.com/winlinvip/simple-rtmp-server/issues/81#issuecomment-48100994
|
// @see: https://github.com/winlinvip/simple-rtmp-server/issues/81#issuecomment-48100994
|
||||||
// it's ok.
|
// it's ok.
|
||||||
srs_trace("-> "SRS_CONSTS_LOG_HLS" time=%"PRId64", stream dts=%"PRId64"(%"PRId64"ms), sno=%d, ts=%s, dur=%.2f, dva=%.2fs/%dp",
|
srs_trace("-> "SRS_CONSTS_LOG_HLS" time=%"PRId64", stream dts=%"PRId64"(%"PRId64"ms), sno=%d, ts=%s, dur=%.2f, dva=%dp",
|
||||||
pprint->age(), stream_dts, stream_dts / 90, muxer->sequence_no(), muxer->ts_url().c_str(),
|
pprint->age(), stream_dts, stream_dts / 90, muxer->sequence_no(), muxer->ts_url().c_str(),
|
||||||
muxer->duration(), muxer->deviation(), muxer->absolute_deviation());
|
muxer->duration(), muxer->deviation());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -199,9 +199,9 @@ private:
|
||||||
private:
|
private:
|
||||||
// whether use floor algorithm for timestamp.
|
// whether use floor algorithm for timestamp.
|
||||||
bool hls_ts_floor;
|
bool hls_ts_floor;
|
||||||
// the deviation in seconds to adjust the fragment to be more
|
// the deviation in piece to adjust the fragment to be more
|
||||||
// bigger or smaller.
|
// bigger or smaller.
|
||||||
double hls_fragment_deviation;
|
int deviation_ts;
|
||||||
// the previous reap floor timestamp,
|
// the previous reap floor timestamp,
|
||||||
// used to detect the dup or jmp or ts.
|
// used to detect the dup or jmp or ts.
|
||||||
int64_t accept_floor_ts;
|
int64_t accept_floor_ts;
|
||||||
|
@ -242,8 +242,7 @@ public:
|
||||||
virtual int sequence_no();
|
virtual int sequence_no();
|
||||||
virtual std::string ts_url();
|
virtual std::string ts_url();
|
||||||
virtual double duration();
|
virtual double duration();
|
||||||
virtual double deviation();
|
virtual int deviation();
|
||||||
virtual int absolute_deviation();
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* initialize the hls muxer.
|
* initialize the hls muxer.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue