fix #108: disable the time jitter for encoder non-monotonical stream. 0.9.133
正在显示
13 个修改的文件
包含
206 行增加
和
28 行删除
| @@ -241,6 +241,7 @@ Supported operating systems and hardware: | @@ -241,6 +241,7 @@ Supported operating systems and hardware: | ||
| 241 | * 2013-10-17, Created.<br/> | 241 | * 2013-10-17, Created.<br/> |
| 242 | 242 | ||
| 243 | ## History | 243 | ## History |
| 244 | +* v1.0, 2014-06-25, fix [#108](https://github.com/winlinvip/simple-rtmp-server/issues/108), disable the time jitter for encoder non-monotonical stream. 0.9.133 | ||
| 244 | * v1.0, 2014-06-23, support report summaries in heartbeat. 0.9.132 | 245 | * v1.0, 2014-06-23, support report summaries in heartbeat. 0.9.132 |
| 245 | * v1.0, 2014-06-22, performance refine, support [3k+](https://github.com/winlinvip/simple-rtmp-server/wiki/Performance#%E6%80%A7%E8%83%BD%E4%BE%8B%E8%A1%8C%E6%8A%A5%E5%91%8A4k) connections(270kbps). 0.9.130 | 246 | * v1.0, 2014-06-22, performance refine, support [3k+](https://github.com/winlinvip/simple-rtmp-server/wiki/Performance#%E6%80%A7%E8%83%BD%E4%BE%8B%E8%A1%8C%E6%8A%A5%E5%91%8A4k) connections(270kbps). 0.9.130 |
| 246 | * v1.0, 2014-06-21, support edge [token traverse](https://github.com/winlinvip/simple-rtmp-server/wiki/DRM#tokentraverse), fix [#104](https://github.com/winlinvip/simple-rtmp-server/issues/104). 0.9.129 | 247 | * v1.0, 2014-06-21, support edge [token traverse](https://github.com/winlinvip/simple-rtmp-server/wiki/DRM#tokentraverse), fix [#104](https://github.com/winlinvip/simple-rtmp-server/issues/104). 0.9.129 |
| @@ -187,6 +187,18 @@ vhost dvr.srs.com { | @@ -187,6 +187,18 @@ vhost dvr.srs.com { | ||
| 187 | # the param for plan(segment), in seconds. | 187 | # the param for plan(segment), in seconds. |
| 188 | # default: 30 | 188 | # default: 30 |
| 189 | dvr_duration 30; | 189 | dvr_duration 30; |
| 190 | + # about the stream monotonically increasing: | ||
| 191 | + # 1. video timestamp is monotonically increasing, | ||
| 192 | + # 2. audio timestamp is monotonically increasing, | ||
| 193 | + # 3. video and audio timestamp is interleaved monotonically increasing. | ||
| 194 | + # it's specified by RTMP specification, @see 3. Byte Order, Alignment, and Time Format | ||
| 195 | + # however, some encoder cannot provides this feature, please set this to off to ignore time jitter. | ||
| 196 | + # the time jitter algorithm: | ||
| 197 | + # 1. full, to ensure stream start at zero, and ensure stream monotonically increasing. | ||
| 198 | + # 2. zero, only ensure sttream start at zero, ignore timestamp jitter. | ||
| 199 | + # 3. off, disable the time jitter algorithm, like atc. | ||
| 200 | + # default: full | ||
| 201 | + time_jitter full; | ||
| 190 | } | 202 | } |
| 191 | } | 203 | } |
| 192 | 204 | ||
| @@ -906,6 +918,22 @@ vhost chunksize.srs.com { | @@ -906,6 +918,22 @@ vhost chunksize.srs.com { | ||
| 906 | chunk_size 128; | 918 | chunk_size 128; |
| 907 | } | 919 | } |
| 908 | 920 | ||
| 921 | +# vhost for time jitter | ||
| 922 | +vhost jitter.srs.com { | ||
| 923 | + # about the stream monotonically increasing: | ||
| 924 | + # 1. video timestamp is monotonically increasing, | ||
| 925 | + # 2. audio timestamp is monotonically increasing, | ||
| 926 | + # 3. video and audio timestamp is interleaved monotonically increasing. | ||
| 927 | + # it's specified by RTMP specification, @see 3. Byte Order, Alignment, and Time Format | ||
| 928 | + # however, some encoder cannot provides this feature, please set this to off to ignore time jitter. | ||
| 929 | + # the time jitter algorithm: | ||
| 930 | + # 1. full, to ensure stream start at zero, and ensure stream monotonically increasing. | ||
| 931 | + # 2. zero, only ensure sttream start at zero, ignore timestamp jitter. | ||
| 932 | + # 3. off, disable the time jitter algorithm, like atc. | ||
| 933 | + # default: full | ||
| 934 | + time_jitter full; | ||
| 935 | +} | ||
| 936 | + | ||
| 909 | # vhost for atc. | 937 | # vhost for atc. |
| 910 | vhost atc.srs.com { | 938 | vhost atc.srs.com { |
| 911 | # vhost for atc for hls/hds/rtmp backup. | 939 | # vhost for atc for hls/hds/rtmp backup. |
| @@ -41,6 +41,7 @@ using namespace std; | @@ -41,6 +41,7 @@ using namespace std; | ||
| 41 | #include <srs_kernel_log.hpp> | 41 | #include <srs_kernel_log.hpp> |
| 42 | #include <srs_protocol_utility.hpp> | 42 | #include <srs_protocol_utility.hpp> |
| 43 | #include <srs_core_autofree.hpp> | 43 | #include <srs_core_autofree.hpp> |
| 44 | +#include <srs_app_source.hpp> | ||
| 44 | 45 | ||
| 45 | #define SRS_WIKI_URL_LOG "https://github.com/winlinvip/simple-rtmp-server/wiki/SrsLog" | 46 | #define SRS_WIKI_URL_LOG "https://github.com/winlinvip/simple-rtmp-server/wiki/SrsLog" |
| 46 | 47 | ||
| @@ -947,6 +948,17 @@ int SrsConfig::reload_vhost(SrsConfDirective* old_root) | @@ -947,6 +948,17 @@ int SrsConfig::reload_vhost(SrsConfDirective* old_root) | ||
| 947 | } | 948 | } |
| 948 | srs_trace("vhost %s reload queue_length success.", vhost.c_str()); | 949 | srs_trace("vhost %s reload queue_length success.", vhost.c_str()); |
| 949 | } | 950 | } |
| 951 | + // time_jitter, only one per vhost | ||
| 952 | + if (!srs_directive_equals(new_vhost->get("time_jitter"), old_vhost->get("time_jitter"))) { | ||
| 953 | + for (it = subscribes.begin(); it != subscribes.end(); ++it) { | ||
| 954 | + ISrsReloadHandler* subscribe = *it; | ||
| 955 | + if ((ret = subscribe->on_reload_vhost_time_jitter(vhost)) != ERROR_SUCCESS) { | ||
| 956 | + srs_error("vhost %s notify subscribes time_jitter failed. ret=%d", vhost.c_str(), ret); | ||
| 957 | + return ret; | ||
| 958 | + } | ||
| 959 | + } | ||
| 960 | + srs_trace("vhost %s reload time_jitter success.", vhost.c_str()); | ||
| 961 | + } | ||
| 950 | // forward, only one per vhost | 962 | // forward, only one per vhost |
| 951 | if (!srs_directive_equals(new_vhost->get("forward"), old_vhost->get("forward"))) { | 963 | if (!srs_directive_equals(new_vhost->get("forward"), old_vhost->get("forward"))) { |
| 952 | for (it = subscribes.begin(); it != subscribes.end(); ++it) { | 964 | for (it = subscribes.begin(); it != subscribes.end(); ++it) { |
| @@ -1788,6 +1800,23 @@ bool SrsConfig::get_atc_auto(string vhost) | @@ -1788,6 +1800,23 @@ bool SrsConfig::get_atc_auto(string vhost) | ||
| 1788 | return true; | 1800 | return true; |
| 1789 | } | 1801 | } |
| 1790 | 1802 | ||
| 1803 | +int SrsConfig::get_time_jitter(string vhost) | ||
| 1804 | +{ | ||
| 1805 | + SrsConfDirective* dvr = get_vhost(vhost); | ||
| 1806 | + | ||
| 1807 | + std::string time_jitter = SRS_CONF_DEFAULT_TIME_JITTER; | ||
| 1808 | + | ||
| 1809 | + if (dvr) { | ||
| 1810 | + SrsConfDirective* conf = dvr->get("time_jitter"); | ||
| 1811 | + | ||
| 1812 | + if (conf) { | ||
| 1813 | + time_jitter = conf->arg0(); | ||
| 1814 | + } | ||
| 1815 | + } | ||
| 1816 | + | ||
| 1817 | + return _srs_time_jitter_string2int(time_jitter); | ||
| 1818 | +} | ||
| 1819 | + | ||
| 1791 | double SrsConfig::get_queue_length(string vhost) | 1820 | double SrsConfig::get_queue_length(string vhost) |
| 1792 | { | 1821 | { |
| 1793 | SrsConfDirective* conf = get_vhost(vhost); | 1822 | SrsConfDirective* conf = get_vhost(vhost); |
| @@ -2636,6 +2665,23 @@ int SrsConfig::get_dvr_duration(string vhost) | @@ -2636,6 +2665,23 @@ int SrsConfig::get_dvr_duration(string vhost) | ||
| 2636 | return ::atoi(conf->arg0().c_str()); | 2665 | return ::atoi(conf->arg0().c_str()); |
| 2637 | } | 2666 | } |
| 2638 | 2667 | ||
| 2668 | +int SrsConfig::get_dvr_time_jitter(string vhost) | ||
| 2669 | +{ | ||
| 2670 | + SrsConfDirective* dvr = get_dvr(vhost); | ||
| 2671 | + | ||
| 2672 | + std::string time_jitter = SRS_CONF_DEFAULT_TIME_JITTER; | ||
| 2673 | + | ||
| 2674 | + if (dvr) { | ||
| 2675 | + SrsConfDirective* conf = dvr->get("time_jitter"); | ||
| 2676 | + | ||
| 2677 | + if (conf) { | ||
| 2678 | + time_jitter = conf->arg0(); | ||
| 2679 | + } | ||
| 2680 | + } | ||
| 2681 | + | ||
| 2682 | + return _srs_time_jitter_string2int(time_jitter); | ||
| 2683 | +} | ||
| 2684 | + | ||
| 2639 | SrsConfDirective* SrsConfig::get_http_api() | 2685 | SrsConfDirective* SrsConfig::get_http_api() |
| 2640 | { | 2686 | { |
| 2641 | return root->get("http_api"); | 2687 | return root->get("http_api"); |
| @@ -49,6 +49,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -49,6 +49,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 49 | #define SRS_CONF_DEFAULT_DVR_PLAN_HSS "hss" | 49 | #define SRS_CONF_DEFAULT_DVR_PLAN_HSS "hss" |
| 50 | #define SRS_CONF_DEFAULT_DVR_PLAN SRS_CONF_DEFAULT_DVR_PLAN_SESSION | 50 | #define SRS_CONF_DEFAULT_DVR_PLAN SRS_CONF_DEFAULT_DVR_PLAN_SESSION |
| 51 | #define SRS_CONF_DEFAULT_DVR_DURATION 30 | 51 | #define SRS_CONF_DEFAULT_DVR_DURATION 30 |
| 52 | +#define SRS_CONF_DEFAULT_TIME_JITTER "full" | ||
| 52 | // in ms, for HLS aac sync time. | 53 | // in ms, for HLS aac sync time. |
| 53 | #define SRS_CONF_DEFAULT_AAC_SYNC 100 | 54 | #define SRS_CONF_DEFAULT_AAC_SYNC 100 |
| 54 | // in ms, for HLS aac flush the audio | 55 | // in ms, for HLS aac flush the audio |
| @@ -200,6 +201,7 @@ public: | @@ -200,6 +201,7 @@ public: | ||
| 200 | virtual bool get_gop_cache(std::string vhost); | 201 | virtual bool get_gop_cache(std::string vhost); |
| 201 | virtual bool get_atc(std::string vhost); | 202 | virtual bool get_atc(std::string vhost); |
| 202 | virtual bool get_atc_auto(std::string vhost); | 203 | virtual bool get_atc_auto(std::string vhost); |
| 204 | + virtual int get_time_jitter(std::string vhost); | ||
| 203 | virtual double get_queue_length(std::string vhost); | 205 | virtual double get_queue_length(std::string vhost); |
| 204 | virtual SrsConfDirective* get_forward(std::string vhost); | 206 | virtual SrsConfDirective* get_forward(std::string vhost); |
| 205 | virtual SrsConfDirective* get_refer(std::string vhost); | 207 | virtual SrsConfDirective* get_refer(std::string vhost); |
| @@ -272,6 +274,7 @@ public: | @@ -272,6 +274,7 @@ public: | ||
| 272 | virtual std::string get_dvr_path(std::string vhost); | 274 | virtual std::string get_dvr_path(std::string vhost); |
| 273 | virtual std::string get_dvr_plan(std::string vhost); | 275 | virtual std::string get_dvr_plan(std::string vhost); |
| 274 | virtual int get_dvr_duration(std::string vhost); | 276 | virtual int get_dvr_duration(std::string vhost); |
| 277 | + virtual int get_dvr_time_jitter(std::string vhost); | ||
| 275 | // http api section | 278 | // http api section |
| 276 | private: | 279 | private: |
| 277 | virtual SrsConfDirective* get_http_api(); | 280 | virtual SrsConfDirective* get_http_api(); |
| @@ -70,10 +70,15 @@ SrsDvrPlan::SrsDvrPlan() | @@ -70,10 +70,15 @@ SrsDvrPlan::SrsDvrPlan() | ||
| 70 | fs = new SrsFileStream(); | 70 | fs = new SrsFileStream(); |
| 71 | enc = new SrsFlvEncoder(); | 71 | enc = new SrsFlvEncoder(); |
| 72 | segment = new SrsFlvSegment(); | 72 | segment = new SrsFlvSegment(); |
| 73 | + jitter_algorithm = SrsRtmpJitterAlgorithmOFF; | ||
| 74 | + | ||
| 75 | + _srs_config->subscribe(this); | ||
| 73 | } | 76 | } |
| 74 | 77 | ||
| 75 | SrsDvrPlan::~SrsDvrPlan() | 78 | SrsDvrPlan::~SrsDvrPlan() |
| 76 | { | 79 | { |
| 80 | + _srs_config->unsubscribe(this); | ||
| 81 | + | ||
| 77 | srs_freep(jitter); | 82 | srs_freep(jitter); |
| 78 | srs_freep(fs); | 83 | srs_freep(fs); |
| 79 | srs_freep(enc); | 84 | srs_freep(enc); |
| @@ -87,6 +92,8 @@ int SrsDvrPlan::initialize(SrsSource* source, SrsRequest* req) | @@ -87,6 +92,8 @@ int SrsDvrPlan::initialize(SrsSource* source, SrsRequest* req) | ||
| 87 | _source = source; | 92 | _source = source; |
| 88 | _req = req; | 93 | _req = req; |
| 89 | 94 | ||
| 95 | + jitter_algorithm = (SrsRtmpJitterAlgorithm)_srs_config->get_dvr_time_jitter(_req->vhost); | ||
| 96 | + | ||
| 90 | return ret; | 97 | return ret; |
| 91 | } | 98 | } |
| 92 | 99 | ||
| @@ -198,7 +205,7 @@ int SrsDvrPlan::on_audio(SrsSharedPtrMessage* audio) | @@ -198,7 +205,7 @@ int SrsDvrPlan::on_audio(SrsSharedPtrMessage* audio) | ||
| 198 | return ret; | 205 | return ret; |
| 199 | } | 206 | } |
| 200 | 207 | ||
| 201 | - if ((jitter->correct(audio, 0, 0)) != ERROR_SUCCESS) { | 208 | + if ((jitter->correct(audio, 0, 0, jitter_algorithm)) != ERROR_SUCCESS) { |
| 202 | return ret; | 209 | return ret; |
| 203 | } | 210 | } |
| 204 | 211 | ||
| @@ -240,7 +247,7 @@ int SrsDvrPlan::on_video(SrsSharedPtrMessage* video) | @@ -240,7 +247,7 @@ int SrsDvrPlan::on_video(SrsSharedPtrMessage* video) | ||
| 240 | srs_verbose("dvr video is key: %d", is_key_frame); | 247 | srs_verbose("dvr video is key: %d", is_key_frame); |
| 241 | #endif | 248 | #endif |
| 242 | 249 | ||
| 243 | - if ((jitter->correct(video, 0, 0)) != ERROR_SUCCESS) { | 250 | + if ((jitter->correct(video, 0, 0, jitter_algorithm)) != ERROR_SUCCESS) { |
| 244 | return ret; | 251 | return ret; |
| 245 | } | 252 | } |
| 246 | 253 | ||
| @@ -256,6 +263,15 @@ int SrsDvrPlan::on_video(SrsSharedPtrMessage* video) | @@ -256,6 +263,15 @@ int SrsDvrPlan::on_video(SrsSharedPtrMessage* video) | ||
| 256 | return ret; | 263 | return ret; |
| 257 | } | 264 | } |
| 258 | 265 | ||
| 266 | +int SrsDvrPlan::on_reload_vhost_dvr(std::string vhost) | ||
| 267 | +{ | ||
| 268 | + int ret = ERROR_SUCCESS; | ||
| 269 | + | ||
| 270 | + jitter_algorithm = (SrsRtmpJitterAlgorithm)_srs_config->get_dvr_time_jitter(_req->vhost); | ||
| 271 | + | ||
| 272 | + return ret; | ||
| 273 | +} | ||
| 274 | + | ||
| 259 | int SrsDvrPlan::flv_open(string stream, string path) | 275 | int SrsDvrPlan::flv_open(string stream, string path) |
| 260 | { | 276 | { |
| 261 | int ret = ERROR_SUCCESS; | 277 | int ret = ERROR_SUCCESS; |
| @@ -42,6 +42,9 @@ class SrsSharedPtrMessage; | @@ -42,6 +42,9 @@ class SrsSharedPtrMessage; | ||
| 42 | class SrsFileStream; | 42 | class SrsFileStream; |
| 43 | class SrsFlvEncoder; | 43 | class SrsFlvEncoder; |
| 44 | 44 | ||
| 45 | +#include <srs_app_source.hpp> | ||
| 46 | +#include <srs_app_reload.hpp> | ||
| 47 | + | ||
| 45 | /** | 48 | /** |
| 46 | * a piece of flv segment. | 49 | * a piece of flv segment. |
| 47 | */ | 50 | */ |
| @@ -93,21 +96,23 @@ public: | @@ -93,21 +96,23 @@ public: | ||
| 93 | * 2. reap flv: when to reap the flv and start new piece. | 96 | * 2. reap flv: when to reap the flv and start new piece. |
| 94 | */ | 97 | */ |
| 95 | // TODO: FIXME: the plan is too fat, refine me. | 98 | // TODO: FIXME: the plan is too fat, refine me. |
| 96 | -class SrsDvrPlan | 99 | +class SrsDvrPlan : public ISrsReloadHandler |
| 97 | { | 100 | { |
| 98 | -protected: | 101 | +private: |
| 99 | /** | 102 | /** |
| 100 | * the underlayer dvr stream. | 103 | * the underlayer dvr stream. |
| 101 | * if close, the flv is reap and closed. | 104 | * if close, the flv is reap and closed. |
| 102 | * if open, new flv file is crote. | 105 | * if open, new flv file is crote. |
| 103 | */ | 106 | */ |
| 104 | - SrsFileStream* fs; | ||
| 105 | SrsFlvEncoder* enc; | 107 | SrsFlvEncoder* enc; |
| 106 | - bool dvr_enabled; | ||
| 107 | SrsSource* _source; | 108 | SrsSource* _source; |
| 108 | - SrsRequest* _req; | ||
| 109 | SrsRtmpJitter* jitter; | 109 | SrsRtmpJitter* jitter; |
| 110 | + SrsRtmpJitterAlgorithm jitter_algorithm; | ||
| 111 | +protected: | ||
| 110 | SrsFlvSegment* segment; | 112 | SrsFlvSegment* segment; |
| 113 | + SrsRequest* _req; | ||
| 114 | + bool dvr_enabled; | ||
| 115 | + SrsFileStream* fs; | ||
| 111 | public: | 116 | public: |
| 112 | SrsDvrPlan(); | 117 | SrsDvrPlan(); |
| 113 | virtual ~SrsDvrPlan(); | 118 | virtual ~SrsDvrPlan(); |
| @@ -118,6 +123,9 @@ public: | @@ -118,6 +123,9 @@ public: | ||
| 118 | virtual int on_meta_data(SrsOnMetaDataPacket* metadata); | 123 | virtual int on_meta_data(SrsOnMetaDataPacket* metadata); |
| 119 | virtual int on_audio(SrsSharedPtrMessage* audio); | 124 | virtual int on_audio(SrsSharedPtrMessage* audio); |
| 120 | virtual int on_video(SrsSharedPtrMessage* video); | 125 | virtual int on_video(SrsSharedPtrMessage* video); |
| 126 | +// interface ISrsReloadHandler | ||
| 127 | +public: | ||
| 128 | + virtual int on_reload_vhost_dvr(std::string vhost); | ||
| 121 | protected: | 129 | protected: |
| 122 | virtual int flv_open(std::string stream, std::string path); | 130 | virtual int flv_open(std::string stream, std::string path); |
| 123 | virtual int flv_close(); | 131 | virtual int flv_close(); |
| @@ -162,7 +162,7 @@ int SrsForwarder::on_meta_data(SrsSharedPtrMessage* metadata) | @@ -162,7 +162,7 @@ int SrsForwarder::on_meta_data(SrsSharedPtrMessage* metadata) | ||
| 162 | { | 162 | { |
| 163 | int ret = ERROR_SUCCESS; | 163 | int ret = ERROR_SUCCESS; |
| 164 | 164 | ||
| 165 | - if ((ret = jitter->correct(metadata, 0, 0)) != ERROR_SUCCESS) { | 165 | + if ((ret = jitter->correct(metadata, 0, 0, SrsRtmpJitterAlgorithmFULL)) != ERROR_SUCCESS) { |
| 166 | srs_freep(metadata); | 166 | srs_freep(metadata); |
| 167 | return ret; | 167 | return ret; |
| 168 | } | 168 | } |
| @@ -178,7 +178,7 @@ int SrsForwarder::on_audio(SrsSharedPtrMessage* msg) | @@ -178,7 +178,7 @@ int SrsForwarder::on_audio(SrsSharedPtrMessage* msg) | ||
| 178 | { | 178 | { |
| 179 | int ret = ERROR_SUCCESS; | 179 | int ret = ERROR_SUCCESS; |
| 180 | 180 | ||
| 181 | - if ((ret = jitter->correct(msg, 0, 0)) != ERROR_SUCCESS) { | 181 | + if ((ret = jitter->correct(msg, 0, 0, SrsRtmpJitterAlgorithmFULL)) != ERROR_SUCCESS) { |
| 182 | srs_freep(msg); | 182 | srs_freep(msg); |
| 183 | return ret; | 183 | return ret; |
| 184 | } | 184 | } |
| @@ -194,7 +194,7 @@ int SrsForwarder::on_video(SrsSharedPtrMessage* msg) | @@ -194,7 +194,7 @@ int SrsForwarder::on_video(SrsSharedPtrMessage* msg) | ||
| 194 | { | 194 | { |
| 195 | int ret = ERROR_SUCCESS; | 195 | int ret = ERROR_SUCCESS; |
| 196 | 196 | ||
| 197 | - if ((ret = jitter->correct(msg, 0, 0)) != ERROR_SUCCESS) { | 197 | + if ((ret = jitter->correct(msg, 0, 0, SrsRtmpJitterAlgorithmFULL)) != ERROR_SUCCESS) { |
| 198 | srs_freep(msg); | 198 | srs_freep(msg); |
| 199 | return ret; | 199 | return ret; |
| 200 | } | 200 | } |
| @@ -1411,7 +1411,7 @@ int SrsHls::on_audio(SrsSharedPtrMessage* audio) | @@ -1411,7 +1411,7 @@ int SrsHls::on_audio(SrsSharedPtrMessage* audio) | ||
| 1411 | return hls_cache->on_sequence_header(muxer); | 1411 | return hls_cache->on_sequence_header(muxer); |
| 1412 | } | 1412 | } |
| 1413 | 1413 | ||
| 1414 | - if ((ret = jitter->correct(audio, 0, 0)) != ERROR_SUCCESS) { | 1414 | + if ((ret = jitter->correct(audio, 0, 0, SrsRtmpJitterAlgorithmFULL)) != ERROR_SUCCESS) { |
| 1415 | srs_error("rtmp jitter correct audio failed. ret=%d", ret); | 1415 | srs_error("rtmp jitter correct audio failed. ret=%d", ret); |
| 1416 | return ret; | 1416 | return ret; |
| 1417 | } | 1417 | } |
| @@ -1456,7 +1456,7 @@ int SrsHls::on_video(SrsSharedPtrMessage* video) | @@ -1456,7 +1456,7 @@ int SrsHls::on_video(SrsSharedPtrMessage* video) | ||
| 1456 | return hls_cache->on_sequence_header(muxer); | 1456 | return hls_cache->on_sequence_header(muxer); |
| 1457 | } | 1457 | } |
| 1458 | 1458 | ||
| 1459 | - if ((ret = jitter->correct(video, 0, 0)) != ERROR_SUCCESS) { | 1459 | + if ((ret = jitter->correct(video, 0, 0, SrsRtmpJitterAlgorithmFULL)) != ERROR_SUCCESS) { |
| 1460 | srs_error("rtmp jitter correct video failed. ret=%d", ret); | 1460 | srs_error("rtmp jitter correct video failed. ret=%d", ret); |
| 1461 | return ret; | 1461 | return ret; |
| 1462 | } | 1462 | } |
| @@ -120,6 +120,11 @@ int ISrsReloadHandler::on_reload_vhost_queue_length(string /*vhost*/) | @@ -120,6 +120,11 @@ int ISrsReloadHandler::on_reload_vhost_queue_length(string /*vhost*/) | ||
| 120 | return ERROR_SUCCESS; | 120 | return ERROR_SUCCESS; |
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | +int ISrsReloadHandler::on_reload_vhost_time_jitter(string /*vhost*/) | ||
| 124 | +{ | ||
| 125 | + return ERROR_SUCCESS; | ||
| 126 | +} | ||
| 127 | + | ||
| 123 | int ISrsReloadHandler::on_reload_vhost_forward(string /*vhost*/) | 128 | int ISrsReloadHandler::on_reload_vhost_forward(string /*vhost*/) |
| 124 | { | 129 | { |
| 125 | return ERROR_SUCCESS; | 130 | return ERROR_SUCCESS; |
| @@ -61,6 +61,7 @@ public: | @@ -61,6 +61,7 @@ public: | ||
| 61 | virtual int on_reload_vhost_atc(std::string vhost); | 61 | virtual int on_reload_vhost_atc(std::string vhost); |
| 62 | virtual int on_reload_vhost_gop_cache(std::string vhost); | 62 | virtual int on_reload_vhost_gop_cache(std::string vhost); |
| 63 | virtual int on_reload_vhost_queue_length(std::string vhost); | 63 | virtual int on_reload_vhost_queue_length(std::string vhost); |
| 64 | + virtual int on_reload_vhost_time_jitter(std::string vhost); | ||
| 64 | virtual int on_reload_vhost_forward(std::string vhost); | 65 | virtual int on_reload_vhost_forward(std::string vhost); |
| 65 | virtual int on_reload_vhost_hls(std::string vhost); | 66 | virtual int on_reload_vhost_hls(std::string vhost); |
| 66 | virtual int on_reload_vhost_dvr(std::string vhost); | 67 | virtual int on_reload_vhost_dvr(std::string vhost); |
| @@ -45,6 +45,17 @@ using namespace std; | @@ -45,6 +45,17 @@ using namespace std; | ||
| 45 | #define CONST_MAX_JITTER_MS 500 | 45 | #define CONST_MAX_JITTER_MS 500 |
| 46 | #define DEFAULT_FRAME_TIME_MS 40 | 46 | #define DEFAULT_FRAME_TIME_MS 40 |
| 47 | 47 | ||
| 48 | +int _srs_time_jitter_string2int(std::string time_jitter) | ||
| 49 | +{ | ||
| 50 | + if (time_jitter == "full") { | ||
| 51 | + return SrsRtmpJitterAlgorithmFULL; | ||
| 52 | + } else if (time_jitter == "zero") { | ||
| 53 | + return SrsRtmpJitterAlgorithmZERO; | ||
| 54 | + } else { | ||
| 55 | + return SrsRtmpJitterAlgorithmOFF; | ||
| 56 | + } | ||
| 57 | +} | ||
| 58 | + | ||
| 48 | SrsRtmpJitter::SrsRtmpJitter() | 59 | SrsRtmpJitter::SrsRtmpJitter() |
| 49 | { | 60 | { |
| 50 | last_pkt_correct_time = last_pkt_time = 0; | 61 | last_pkt_correct_time = last_pkt_time = 0; |
| @@ -54,10 +65,27 @@ SrsRtmpJitter::~SrsRtmpJitter() | @@ -54,10 +65,27 @@ SrsRtmpJitter::~SrsRtmpJitter() | ||
| 54 | { | 65 | { |
| 55 | } | 66 | } |
| 56 | 67 | ||
| 57 | -int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, int tba, int tbv) | 68 | +int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, int tba, int tbv, SrsRtmpJitterAlgorithm ag) |
| 58 | { | 69 | { |
| 59 | int ret = ERROR_SUCCESS; | 70 | int ret = ERROR_SUCCESS; |
| 60 | 71 | ||
| 72 | + // all jitter correct features is disabled, ignore. | ||
| 73 | + if (ag == SrsRtmpJitterAlgorithmOFF) { | ||
| 74 | + return ret; | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + | ||
| 78 | + // start at zero, but donot ensure monotonically increasing. | ||
| 79 | + if (ag == SrsRtmpJitterAlgorithmZERO) { | ||
| 80 | + if (last_pkt_correct_time <= 0) { | ||
| 81 | + last_pkt_correct_time = msg->header.timestamp; | ||
| 82 | + } | ||
| 83 | + msg->header.timestamp -= last_pkt_correct_time; | ||
| 84 | + return ret; | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + // full jitter algorithm, do jitter correct. | ||
| 88 | + | ||
| 61 | // set to 0 for metadata. | 89 | // set to 0 for metadata. |
| 62 | if (!msg->header.is_video() && !msg->header.is_audio()) { | 90 | if (!msg->header.is_video() && !msg->header.is_audio()) { |
| 63 | msg->header.timestamp = 0; | 91 | msg->header.timestamp = 0; |
| @@ -266,12 +294,12 @@ int SrsConsumer::get_time() | @@ -266,12 +294,12 @@ int SrsConsumer::get_time() | ||
| 266 | return jitter->get_time(); | 294 | return jitter->get_time(); |
| 267 | } | 295 | } |
| 268 | 296 | ||
| 269 | -int SrsConsumer::enqueue(SrsSharedPtrMessage* msg, bool atc, int tba, int tbv) | 297 | +int SrsConsumer::enqueue(SrsSharedPtrMessage* msg, bool atc, int tba, int tbv, SrsRtmpJitterAlgorithm ag) |
| 270 | { | 298 | { |
| 271 | int ret = ERROR_SUCCESS; | 299 | int ret = ERROR_SUCCESS; |
| 272 | 300 | ||
| 273 | if (!atc) { | 301 | if (!atc) { |
| 274 | - if ((ret = jitter->correct(msg, tba, tbv)) != ERROR_SUCCESS) { | 302 | + if ((ret = jitter->correct(msg, tba, tbv, ag)) != ERROR_SUCCESS) { |
| 275 | srs_freep(msg); | 303 | srs_freep(msg); |
| 276 | return ret; | 304 | return ret; |
| 277 | } | 305 | } |
| @@ -384,7 +412,7 @@ void SrsGopCache::clear() | @@ -384,7 +412,7 @@ void SrsGopCache::clear() | ||
| 384 | cached_video_count = 0; | 412 | cached_video_count = 0; |
| 385 | } | 413 | } |
| 386 | 414 | ||
| 387 | -int SrsGopCache::dump(SrsConsumer* consumer, bool atc, int tba, int tbv) | 415 | +int SrsGopCache::dump(SrsConsumer* consumer, bool atc, int tba, int tbv, SrsRtmpJitterAlgorithm jitter_algorithm) |
| 388 | { | 416 | { |
| 389 | int ret = ERROR_SUCCESS; | 417 | int ret = ERROR_SUCCESS; |
| 390 | 418 | ||
| @@ -392,7 +420,7 @@ int SrsGopCache::dump(SrsConsumer* consumer, bool atc, int tba, int tbv) | @@ -392,7 +420,7 @@ int SrsGopCache::dump(SrsConsumer* consumer, bool atc, int tba, int tbv) | ||
| 392 | for (it = gop_cache.begin(); it != gop_cache.end(); ++it) { | 420 | for (it = gop_cache.begin(); it != gop_cache.end(); ++it) { |
| 393 | SrsSharedPtrMessage* msg = *it; | 421 | SrsSharedPtrMessage* msg = *it; |
| 394 | SrsSharedPtrMessage* copy = msg->copy(); | 422 | SrsSharedPtrMessage* copy = msg->copy(); |
| 395 | - if ((ret = consumer->enqueue(copy, atc, tba, tbv)) != ERROR_SUCCESS) { | 423 | + if ((ret = consumer->enqueue(copy, atc, tba, tbv, jitter_algorithm)) != ERROR_SUCCESS) { |
| 396 | srs_error("dispatch cached gop failed. ret=%d", ret); | 424 | srs_error("dispatch cached gop failed. ret=%d", ret); |
| 397 | return ret; | 425 | return ret; |
| 398 | } | 426 | } |
| @@ -464,6 +492,7 @@ void SrsSource::destroy() | @@ -464,6 +492,7 @@ void SrsSource::destroy() | ||
| 464 | SrsSource::SrsSource(SrsRequest* req) | 492 | SrsSource::SrsSource(SrsRequest* req) |
| 465 | { | 493 | { |
| 466 | _req = req->copy(); | 494 | _req = req->copy(); |
| 495 | + jitter_algorithm = SrsRtmpJitterAlgorithmOFF; | ||
| 467 | 496 | ||
| 468 | #ifdef SRS_AUTO_HLS | 497 | #ifdef SRS_AUTO_HLS |
| 469 | hls = new SrsHls(this); | 498 | hls = new SrsHls(this); |
| @@ -549,6 +578,8 @@ int SrsSource::initialize() | @@ -549,6 +578,8 @@ int SrsSource::initialize() | ||
| 549 | double queue_size = _srs_config->get_queue_length(_req->vhost); | 578 | double queue_size = _srs_config->get_queue_length(_req->vhost); |
| 550 | publish_edge->set_queue_size(queue_size); | 579 | publish_edge->set_queue_size(queue_size); |
| 551 | 580 | ||
| 581 | + jitter_algorithm = (SrsRtmpJitterAlgorithm)_srs_config->get_time_jitter(_req->vhost); | ||
| 582 | + | ||
| 552 | return ret; | 583 | return ret; |
| 553 | } | 584 | } |
| 554 | 585 | ||
| @@ -630,6 +661,19 @@ int SrsSource::on_reload_vhost_queue_length(string vhost) | @@ -630,6 +661,19 @@ int SrsSource::on_reload_vhost_queue_length(string vhost) | ||
| 630 | return ret; | 661 | return ret; |
| 631 | } | 662 | } |
| 632 | 663 | ||
| 664 | +int SrsSource::on_reload_vhost_time_jitter(string vhost) | ||
| 665 | +{ | ||
| 666 | + int ret = ERROR_SUCCESS; | ||
| 667 | + | ||
| 668 | + if (_req->vhost != vhost) { | ||
| 669 | + return ret; | ||
| 670 | + } | ||
| 671 | + | ||
| 672 | + jitter_algorithm = (SrsRtmpJitterAlgorithm)_srs_config->get_time_jitter(_req->vhost); | ||
| 673 | + | ||
| 674 | + return ret; | ||
| 675 | +} | ||
| 676 | + | ||
| 633 | int SrsSource::on_reload_vhost_forward(string vhost) | 677 | int SrsSource::on_reload_vhost_forward(string vhost) |
| 634 | { | 678 | { |
| 635 | int ret = ERROR_SUCCESS; | 679 | int ret = ERROR_SUCCESS; |
| @@ -928,7 +972,7 @@ int SrsSource::on_meta_data(SrsMessage* msg, SrsOnMetaDataPacket* metadata) | @@ -928,7 +972,7 @@ int SrsSource::on_meta_data(SrsMessage* msg, SrsOnMetaDataPacket* metadata) | ||
| 928 | for (it = consumers.begin(); it != consumers.end(); ++it) { | 972 | for (it = consumers.begin(); it != consumers.end(); ++it) { |
| 929 | SrsConsumer* consumer = *it; | 973 | SrsConsumer* consumer = *it; |
| 930 | SrsSharedPtrMessage* copy = cache_metadata->copy(); | 974 | SrsSharedPtrMessage* copy = cache_metadata->copy(); |
| 931 | - if ((ret = consumer->enqueue(copy, atc, sample_rate, frame_rate)) != ERROR_SUCCESS) { | 975 | + if ((ret = consumer->enqueue(copy, atc, sample_rate, frame_rate, jitter_algorithm)) != ERROR_SUCCESS) { |
| 932 | srs_error("dispatch the metadata failed. ret=%d", ret); | 976 | srs_error("dispatch the metadata failed. ret=%d", ret); |
| 933 | return ret; | 977 | return ret; |
| 934 | } | 978 | } |
| @@ -992,7 +1036,7 @@ int SrsSource::on_audio(SrsMessage* audio) | @@ -992,7 +1036,7 @@ int SrsSource::on_audio(SrsMessage* audio) | ||
| 992 | for (int i = 0; i < (int)consumers.size(); i++) { | 1036 | for (int i = 0; i < (int)consumers.size(); i++) { |
| 993 | SrsConsumer* consumer = consumers.at(i); | 1037 | SrsConsumer* consumer = consumers.at(i); |
| 994 | SrsSharedPtrMessage* copy = msg->copy(); | 1038 | SrsSharedPtrMessage* copy = msg->copy(); |
| 995 | - if ((ret = consumer->enqueue(copy, atc, sample_rate, frame_rate)) != ERROR_SUCCESS) { | 1039 | + if ((ret = consumer->enqueue(copy, atc, sample_rate, frame_rate, jitter_algorithm)) != ERROR_SUCCESS) { |
| 996 | srs_error("dispatch the audio failed. ret=%d", ret); | 1040 | srs_error("dispatch the audio failed. ret=%d", ret); |
| 997 | return ret; | 1041 | return ret; |
| 998 | } | 1042 | } |
| @@ -1082,7 +1126,7 @@ int SrsSource::on_video(SrsMessage* video) | @@ -1082,7 +1126,7 @@ int SrsSource::on_video(SrsMessage* video) | ||
| 1082 | for (int i = 0; i < (int)consumers.size(); i++) { | 1126 | for (int i = 0; i < (int)consumers.size(); i++) { |
| 1083 | SrsConsumer* consumer = consumers.at(i); | 1127 | SrsConsumer* consumer = consumers.at(i); |
| 1084 | SrsSharedPtrMessage* copy = msg->copy(); | 1128 | SrsSharedPtrMessage* copy = msg->copy(); |
| 1085 | - if ((ret = consumer->enqueue(copy, atc, sample_rate, frame_rate)) != ERROR_SUCCESS) { | 1129 | + if ((ret = consumer->enqueue(copy, atc, sample_rate, frame_rate, jitter_algorithm)) != ERROR_SUCCESS) { |
| 1086 | srs_error("dispatch the video failed. ret=%d", ret); | 1130 | srs_error("dispatch the video failed. ret=%d", ret); |
| 1087 | return ret; | 1131 | return ret; |
| 1088 | } | 1132 | } |
| @@ -1328,28 +1372,32 @@ void SrsSource::on_unpublish() | @@ -1328,28 +1372,32 @@ void SrsSource::on_unpublish() | ||
| 1328 | } | 1372 | } |
| 1329 | } | 1373 | } |
| 1330 | 1374 | ||
| 1375 | + int tba = sample_rate; | ||
| 1376 | + int tbv = frame_rate; | ||
| 1377 | + SrsRtmpJitterAlgorithm ag = jitter_algorithm; | ||
| 1378 | + | ||
| 1331 | // copy metadata. | 1379 | // copy metadata. |
| 1332 | - if (cache_metadata && (ret = consumer->enqueue(cache_metadata->copy(), atc, sample_rate, frame_rate)) != ERROR_SUCCESS) { | 1380 | + if (cache_metadata && (ret = consumer->enqueue(cache_metadata->copy(), atc, tba, tbv, ag)) != ERROR_SUCCESS) { |
| 1333 | srs_error("dispatch metadata failed. ret=%d", ret); | 1381 | srs_error("dispatch metadata failed. ret=%d", ret); |
| 1334 | return ret; | 1382 | return ret; |
| 1335 | } | 1383 | } |
| 1336 | srs_info("dispatch metadata success"); | 1384 | srs_info("dispatch metadata success"); |
| 1337 | 1385 | ||
| 1338 | // copy sequence header | 1386 | // copy sequence header |
| 1339 | - if (cache_sh_video && (ret = consumer->enqueue(cache_sh_video->copy(), atc, sample_rate, frame_rate)) != ERROR_SUCCESS) { | 1387 | + if (cache_sh_video && (ret = consumer->enqueue(cache_sh_video->copy(), atc, tba, tbv, ag)) != ERROR_SUCCESS) { |
| 1340 | srs_error("dispatch video sequence header failed. ret=%d", ret); | 1388 | srs_error("dispatch video sequence header failed. ret=%d", ret); |
| 1341 | return ret; | 1389 | return ret; |
| 1342 | } | 1390 | } |
| 1343 | srs_info("dispatch video sequence header success"); | 1391 | srs_info("dispatch video sequence header success"); |
| 1344 | 1392 | ||
| 1345 | - if (cache_sh_audio && (ret = consumer->enqueue(cache_sh_audio->copy(), atc, sample_rate, frame_rate)) != ERROR_SUCCESS) { | 1393 | + if (cache_sh_audio && (ret = consumer->enqueue(cache_sh_audio->copy(), atc, tba, tbv, ag)) != ERROR_SUCCESS) { |
| 1346 | srs_error("dispatch audio sequence header failed. ret=%d", ret); | 1394 | srs_error("dispatch audio sequence header failed. ret=%d", ret); |
| 1347 | return ret; | 1395 | return ret; |
| 1348 | } | 1396 | } |
| 1349 | srs_info("dispatch audio sequence header success"); | 1397 | srs_info("dispatch audio sequence header success"); |
| 1350 | 1398 | ||
| 1351 | // copy gop cache to client. | 1399 | // copy gop cache to client. |
| 1352 | - if ((ret = gop_cache->dump(consumer, atc, sample_rate, frame_rate)) != ERROR_SUCCESS) { | 1400 | + if ((ret = gop_cache->dump(consumer, atc, tba, tbv, ag)) != ERROR_SUCCESS) { |
| 1353 | return ret; | 1401 | return ret; |
| 1354 | } | 1402 | } |
| 1355 | 1403 |
| @@ -60,6 +60,20 @@ class SrsEncoder; | @@ -60,6 +60,20 @@ class SrsEncoder; | ||
| 60 | class SrsStream; | 60 | class SrsStream; |
| 61 | 61 | ||
| 62 | /** | 62 | /** |
| 63 | +* the time jitter algorithm: | ||
| 64 | +* 1. full, to ensure stream start at zero, and ensure stream monotonically increasing. | ||
| 65 | +* 2. zero, only ensure sttream start at zero, ignore timestamp jitter. | ||
| 66 | +* 3. off, disable the time jitter algorithm, like atc. | ||
| 67 | +*/ | ||
| 68 | +enum SrsRtmpJitterAlgorithm | ||
| 69 | +{ | ||
| 70 | + SrsRtmpJitterAlgorithmFULL = 0x01, | ||
| 71 | + SrsRtmpJitterAlgorithmZERO, | ||
| 72 | + SrsRtmpJitterAlgorithmOFF | ||
| 73 | +}; | ||
| 74 | +int _srs_time_jitter_string2int(std::string time_jitter); | ||
| 75 | + | ||
| 76 | +/** | ||
| 63 | * time jitter detect and correct, | 77 | * time jitter detect and correct, |
| 64 | * to ensure the rtmp stream is monotonically. | 78 | * to ensure the rtmp stream is monotonically. |
| 65 | */ | 79 | */ |
| @@ -74,8 +88,12 @@ public: | @@ -74,8 +88,12 @@ public: | ||
| 74 | public: | 88 | public: |
| 75 | /** | 89 | /** |
| 76 | * detect the time jitter and correct it. | 90 | * detect the time jitter and correct it. |
| 91 | + * @param tba, the audio timebase, used to calc the "right" delta if jitter detected. | ||
| 92 | + * @param tbv, the video timebase, used to calc the "right" delta if jitter detected. | ||
| 93 | + * @param start_at_zero whether ensure stream start at zero. | ||
| 94 | + * @param mono_increasing whether ensure stream is monotonically inscreasing. | ||
| 77 | */ | 95 | */ |
| 78 | - virtual int correct(SrsSharedPtrMessage* msg, int tba, int tbv); | 96 | + virtual int correct(SrsSharedPtrMessage* msg, int tba, int tbv, SrsRtmpJitterAlgorithm ag); |
| 79 | /** | 97 | /** |
| 80 | * get current client time, the last packet time. | 98 | * get current client time, the last packet time. |
| 81 | */ | 99 | */ |
| @@ -160,8 +178,9 @@ public: | @@ -160,8 +178,9 @@ public: | ||
| 160 | * used to calc the audio time delta if time-jitter detected. | 178 | * used to calc the audio time delta if time-jitter detected. |
| 161 | * @param tbv timebase of video. | 179 | * @param tbv timebase of video. |
| 162 | * used to calc the video time delta if time-jitter detected. | 180 | * used to calc the video time delta if time-jitter detected. |
| 181 | + * @param ag the algorithm of time jitter. | ||
| 163 | */ | 182 | */ |
| 164 | - virtual int enqueue(SrsSharedPtrMessage* msg, bool atc, int tba, int tbv); | 183 | + virtual int enqueue(SrsSharedPtrMessage* msg, bool atc, int tba, int tbv, SrsRtmpJitterAlgorithm ag); |
| 165 | /** | 184 | /** |
| 166 | * get packets in consumer queue. | 185 | * get packets in consumer queue. |
| 167 | * @pmsgs SrsMessages*[], used to store the msgs, user must alloc it. | 186 | * @pmsgs SrsMessages*[], used to store the msgs, user must alloc it. |
| @@ -209,7 +228,7 @@ public: | @@ -209,7 +228,7 @@ public: | ||
| 209 | */ | 228 | */ |
| 210 | virtual int cache(SrsSharedPtrMessage* msg); | 229 | virtual int cache(SrsSharedPtrMessage* msg); |
| 211 | virtual void clear(); | 230 | virtual void clear(); |
| 212 | - virtual int dump(SrsConsumer* consumer, bool atc, int tba, int tbv); | 231 | + virtual int dump(SrsConsumer* consumer, bool atc, int tba, int tbv, SrsRtmpJitterAlgorithm jitter_algorithm); |
| 213 | /** | 232 | /** |
| 214 | * used for atc to get the time of gop cache, | 233 | * used for atc to get the time of gop cache, |
| 215 | * the atc will adjust the sequence header timestamp to gop cache. | 234 | * the atc will adjust the sequence header timestamp to gop cache. |
| @@ -249,6 +268,8 @@ private: | @@ -249,6 +268,8 @@ private: | ||
| 249 | SrsRequest* _req; | 268 | SrsRequest* _req; |
| 250 | // to delivery stream to clients. | 269 | // to delivery stream to clients. |
| 251 | std::vector<SrsConsumer*> consumers; | 270 | std::vector<SrsConsumer*> consumers; |
| 271 | + // the time jitter algorithm for vhost. | ||
| 272 | + SrsRtmpJitterAlgorithm jitter_algorithm; | ||
| 252 | // hls handler. | 273 | // hls handler. |
| 253 | #ifdef SRS_AUTO_HLS | 274 | #ifdef SRS_AUTO_HLS |
| 254 | SrsHls* hls; | 275 | SrsHls* hls; |
| @@ -310,6 +331,7 @@ public: | @@ -310,6 +331,7 @@ public: | ||
| 310 | virtual int on_reload_vhost_atc(std::string vhost); | 331 | virtual int on_reload_vhost_atc(std::string vhost); |
| 311 | virtual int on_reload_vhost_gop_cache(std::string vhost); | 332 | virtual int on_reload_vhost_gop_cache(std::string vhost); |
| 312 | virtual int on_reload_vhost_queue_length(std::string vhost); | 333 | virtual int on_reload_vhost_queue_length(std::string vhost); |
| 334 | + virtual int on_reload_vhost_time_jitter(std::string vhost); | ||
| 313 | virtual int on_reload_vhost_forward(std::string vhost); | 335 | virtual int on_reload_vhost_forward(std::string vhost); |
| 314 | virtual int on_reload_vhost_hls(std::string vhost); | 336 | virtual int on_reload_vhost_hls(std::string vhost); |
| 315 | virtual int on_reload_vhost_dvr(std::string vhost); | 337 | virtual int on_reload_vhost_dvr(std::string vhost); |
| @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 31 | // current release version | 31 | // current release version |
| 32 | #define VERSION_MAJOR "0" | 32 | #define VERSION_MAJOR "0" |
| 33 | #define VERSION_MINOR "9" | 33 | #define VERSION_MINOR "9" |
| 34 | -#define VERSION_REVISION "132" | 34 | +#define VERSION_REVISION "133" |
| 35 | #define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION | 35 | #define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION |
| 36 | // server info. | 36 | // server info. |
| 37 | #define RTMP_SIG_SRS_KEY "SRS" | 37 | #define RTMP_SIG_SRS_KEY "SRS" |
-
请 注册 或 登录 后发表评论