Support RTMP ATC for HLS/HDS to support backup(failover). change to 0.9.35
正在显示
8 个修改的文件
包含
120 行增加
和
13 行删除
| @@ -112,13 +112,13 @@ Supported operating systems and hardware: | @@ -112,13 +112,13 @@ Supported operating systems and hardware: | ||
| 112 | 26. Support RTMP(play-publish) library: srs-librtmp<br/> | 112 | 26. Support RTMP(play-publish) library: srs-librtmp<br/> |
| 113 | 27. Support ARM([debian armhf, v7cpu](https://github.com/winlinvip/simple-rtmp-server/wiki/SrsLinuxArm)) with rtmp/ssl/hls/librtmp.<br/> | 113 | 27. Support ARM([debian armhf, v7cpu](https://github.com/winlinvip/simple-rtmp-server/wiki/SrsLinuxArm)) with rtmp/ssl/hls/librtmp.<br/> |
| 114 | 28. Support [init.d](https://github.com/winlinvip/simple-rtmp-server/wiki/LinuxService) and packge script, log to file. <br/> | 114 | 28. Support [init.d](https://github.com/winlinvip/simple-rtmp-server/wiki/LinuxService) and packge script, log to file. <br/> |
| 115 | -29. [plan] Support system utest<br/> | ||
| 116 | -30. [plan] Support embeded http server for api and hls(live/vod)<br/> | ||
| 117 | -31. [plan] Support vod(file to hls stream)<br/> | ||
| 118 | -32. [plan] Support stream ingester using ffmpeg.<br/> | ||
| 119 | -33. [plan] Support ingest RTSP(RTP, SDP) stream to RTMP.<br/> | ||
| 120 | -34. [plan] Support network based cli and json result.<br/> | ||
| 121 | -35. [plan] Support HLS cluster, use RTMP ATC to generate the TS<br/> | 115 | +29. Support RTMP ATC for HLS/HDS to support backup(failover)<br/> |
| 116 | +30. [plan] Support system utest<br/> | ||
| 117 | +31. [plan] Support embeded http server for api and hls(live/vod)<br/> | ||
| 118 | +32. [plan] Support vod(file to hls stream)<br/> | ||
| 119 | +33. [plan] Support stream ingester using ffmpeg.<br/> | ||
| 120 | +34. [plan] Support ingest RTSP(RTP, SDP) stream to RTMP.<br/> | ||
| 121 | +35. [plan] Support network based cli and json result.<br/> | ||
| 122 | 36. [plan] Support RTMP edge server, push/pull stream from any RTMP server<br/> | 122 | 36. [plan] Support RTMP edge server, push/pull stream from any RTMP server<br/> |
| 123 | 37. [plan] Support multiple processes, for both origin and edge<br/> | 123 | 37. [plan] Support multiple processes, for both origin and edge<br/> |
| 124 | 38. [no-plan] Support adobe flash refer/token/swf verification.<br/> | 124 | 38. [no-plan] Support adobe flash refer/token/swf verification.<br/> |
| @@ -41,6 +41,23 @@ vhost __defaultVhost__ { | @@ -41,6 +41,23 @@ vhost __defaultVhost__ { | ||
| 41 | gop_cache on; | 41 | gop_cache on; |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | +# vhost for atc. | ||
| 45 | +vhost atc.srs.com { | ||
| 46 | + # vhost for atc for hls/hds/rtmp backup. | ||
| 47 | + # generally, atc default to off, server delivery rtmp stream to client(flash) timestamp from 0. | ||
| 48 | + # when atc is on, server delivery rtmp stream by absolute time. | ||
| 49 | + # atc is used, for instance, encoder will copy stream to master and slave server, | ||
| 50 | + # server use atc to delivery stream to edge/client, where stream time from master/slave server | ||
| 51 | + # is always the same, client/tools can slice RTMP stream to HLS according to the same time, | ||
| 52 | + # if the time not the same, the HLS stream cannot slice to support system backup. | ||
| 53 | + # | ||
| 54 | + # @see http://www.adobe.com/cn/devnet/adobe-media-server/articles/varnish-sample-for-failover.html | ||
| 55 | + # @see http://www.baidu.com/#wd=hds%20hls%20atc | ||
| 56 | + # | ||
| 57 | + # default: off | ||
| 58 | + atc on; | ||
| 59 | +} | ||
| 60 | + | ||
| 44 | # vhost for bandwidth check | 61 | # vhost for bandwidth check |
| 45 | # generally, the bandcheck vhost must be: bandcheck.srs.com, | 62 | # generally, the bandcheck vhost must be: bandcheck.srs.com, |
| 46 | # or need to modify the vhost of client. | 63 | # or need to modify the vhost of client. |
| @@ -1340,6 +1340,22 @@ bool SrsConfig::get_gop_cache(string vhost) | @@ -1340,6 +1340,22 @@ bool SrsConfig::get_gop_cache(string vhost) | ||
| 1340 | return true; | 1340 | return true; |
| 1341 | } | 1341 | } |
| 1342 | 1342 | ||
| 1343 | +bool SrsConfig::get_atc(string vhost) | ||
| 1344 | +{ | ||
| 1345 | + SrsConfDirective* conf = get_vhost(vhost); | ||
| 1346 | + | ||
| 1347 | + if (!conf) { | ||
| 1348 | + return true; | ||
| 1349 | + } | ||
| 1350 | + | ||
| 1351 | + conf = conf->get("atc"); | ||
| 1352 | + if (conf && conf->arg0() == "on") { | ||
| 1353 | + return true; | ||
| 1354 | + } | ||
| 1355 | + | ||
| 1356 | + return false; | ||
| 1357 | +} | ||
| 1358 | + | ||
| 1343 | double SrsConfig::get_queue_length(string vhost) | 1359 | double SrsConfig::get_queue_length(string vhost) |
| 1344 | { | 1360 | { |
| 1345 | SrsConfDirective* conf = get_vhost(vhost); | 1361 | SrsConfDirective* conf = get_vhost(vhost); |
| @@ -153,6 +153,7 @@ public: | @@ -153,6 +153,7 @@ public: | ||
| 153 | virtual bool get_deamon(); | 153 | virtual bool get_deamon(); |
| 154 | virtual int get_max_connections(); | 154 | virtual int get_max_connections(); |
| 155 | virtual bool get_gop_cache(std::string vhost); | 155 | virtual bool get_gop_cache(std::string vhost); |
| 156 | + virtual bool get_atc(std::string vhost); | ||
| 156 | virtual double get_queue_length(std::string vhost); | 157 | virtual double get_queue_length(std::string vhost); |
| 157 | virtual SrsConfDirective* get_forward(std::string vhost); | 158 | virtual SrsConfDirective* get_forward(std::string vhost); |
| 158 | private: | 159 | private: |
| @@ -268,10 +268,11 @@ int SrsConsumer::enqueue(SrsSharedPtrMessage* msg, int tba, int tbv) | @@ -268,10 +268,11 @@ int SrsConsumer::enqueue(SrsSharedPtrMessage* msg, int tba, int tbv) | ||
| 268 | { | 268 | { |
| 269 | int ret = ERROR_SUCCESS; | 269 | int ret = ERROR_SUCCESS; |
| 270 | 270 | ||
| 271 | - /* TODO: to support atc */ | ||
| 272 | - if ((ret = jitter->correct(msg, tba, tbv)) != ERROR_SUCCESS) { | ||
| 273 | - srs_freep(msg); | ||
| 274 | - return ret; | 271 | + if (!source->is_atc()) { |
| 272 | + if ((ret = jitter->correct(msg, tba, tbv)) != ERROR_SUCCESS) { | ||
| 273 | + srs_freep(msg); | ||
| 274 | + return ret; | ||
| 275 | + } | ||
| 275 | } | 276 | } |
| 276 | 277 | ||
| 277 | if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) { | 278 | if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) { |
| @@ -391,6 +392,23 @@ int SrsGopCache::dump(SrsConsumer* consumer, int tba, int tbv) | @@ -391,6 +392,23 @@ int SrsGopCache::dump(SrsConsumer* consumer, int tba, int tbv) | ||
| 391 | return ret; | 392 | return ret; |
| 392 | } | 393 | } |
| 393 | 394 | ||
| 395 | +bool SrsGopCache::empty() | ||
| 396 | +{ | ||
| 397 | + return gop_cache.empty(); | ||
| 398 | +} | ||
| 399 | + | ||
| 400 | +int64_t SrsGopCache::get_start_time() | ||
| 401 | +{ | ||
| 402 | + if (empty()) { | ||
| 403 | + return 0; | ||
| 404 | + } | ||
| 405 | + | ||
| 406 | + SrsSharedPtrMessage* msg = gop_cache[0]; | ||
| 407 | + srs_assert(msg); | ||
| 408 | + | ||
| 409 | + return msg->header.timestamp; | ||
| 410 | +} | ||
| 411 | + | ||
| 394 | std::map<std::string, SrsSource*> SrsSource::pool; | 412 | std::map<std::string, SrsSource*> SrsSource::pool; |
| 395 | 413 | ||
| 396 | SrsSource* SrsSource::find(SrsRequest* req) | 414 | SrsSource* SrsSource::find(SrsRequest* req) |
| @@ -425,6 +443,7 @@ SrsSource::SrsSource(SrsRequest* _req) | @@ -425,6 +443,7 @@ SrsSource::SrsSource(SrsRequest* _req) | ||
| 425 | gop_cache = new SrsGopCache(); | 443 | gop_cache = new SrsGopCache(); |
| 426 | 444 | ||
| 427 | _srs_config->subscribe(this); | 445 | _srs_config->subscribe(this); |
| 446 | + atc = _srs_config->get_atc(req->vhost); | ||
| 428 | } | 447 | } |
| 429 | 448 | ||
| 430 | SrsSource::~SrsSource() | 449 | SrsSource::~SrsSource() |
| @@ -774,6 +793,16 @@ int SrsSource::on_audio(SrsCommonMessage* audio) | @@ -774,6 +793,16 @@ int SrsSource::on_audio(SrsCommonMessage* audio) | ||
| 774 | } | 793 | } |
| 775 | srs_verbose("cache gop success."); | 794 | srs_verbose("cache gop success."); |
| 776 | 795 | ||
| 796 | + // if atc, update the sequence header to abs time. | ||
| 797 | + if (atc) { | ||
| 798 | + if (cache_sh_audio) { | ||
| 799 | + cache_sh_audio->header.timestamp = msg->header.timestamp; | ||
| 800 | + } | ||
| 801 | + if (cache_metadata) { | ||
| 802 | + cache_metadata->header.timestamp = msg->header.timestamp; | ||
| 803 | + } | ||
| 804 | + } | ||
| 805 | + | ||
| 777 | return ret; | 806 | return ret; |
| 778 | } | 807 | } |
| 779 | 808 | ||
| @@ -841,6 +870,16 @@ int SrsSource::on_video(SrsCommonMessage* video) | @@ -841,6 +870,16 @@ int SrsSource::on_video(SrsCommonMessage* video) | ||
| 841 | } | 870 | } |
| 842 | srs_verbose("cache gop success."); | 871 | srs_verbose("cache gop success."); |
| 843 | 872 | ||
| 873 | + // if atc, update the sequence header to abs time. | ||
| 874 | + if (atc) { | ||
| 875 | + if (cache_sh_video) { | ||
| 876 | + cache_sh_video->header.timestamp = msg->header.timestamp; | ||
| 877 | + } | ||
| 878 | + if (cache_metadata) { | ||
| 879 | + cache_metadata->header.timestamp = msg->header.timestamp; | ||
| 880 | + } | ||
| 881 | + } | ||
| 882 | + | ||
| 844 | return ret; | 883 | return ret; |
| 845 | } | 884 | } |
| 846 | 885 | ||
| @@ -921,6 +960,17 @@ void SrsSource::on_unpublish() | @@ -921,6 +960,17 @@ void SrsSource::on_unpublish() | ||
| 921 | } | 960 | } |
| 922 | srs_info("dispatch metadata success"); | 961 | srs_info("dispatch metadata success"); |
| 923 | 962 | ||
| 963 | + // if atc, update the sequence header to gop cache time. | ||
| 964 | + if (atc && !gop_cache->empty()) { | ||
| 965 | + if (cache_sh_video) { | ||
| 966 | + cache_sh_video->header.timestamp = gop_cache->get_start_time(); | ||
| 967 | + } | ||
| 968 | + if (cache_sh_audio) { | ||
| 969 | + cache_sh_audio->header.timestamp = gop_cache->get_start_time(); | ||
| 970 | + } | ||
| 971 | + } | ||
| 972 | + | ||
| 973 | + // copy sequence header | ||
| 924 | if (cache_sh_video && (ret = consumer->enqueue(cache_sh_video->copy(), sample_rate, frame_rate)) != ERROR_SUCCESS) { | 974 | if (cache_sh_video && (ret = consumer->enqueue(cache_sh_video->copy(), sample_rate, frame_rate)) != ERROR_SUCCESS) { |
| 925 | srs_error("dispatch video sequence header failed. ret=%d", ret); | 975 | srs_error("dispatch video sequence header failed. ret=%d", ret); |
| 926 | return ret; | 976 | return ret; |
| @@ -933,6 +983,7 @@ void SrsSource::on_unpublish() | @@ -933,6 +983,7 @@ void SrsSource::on_unpublish() | ||
| 933 | } | 983 | } |
| 934 | srs_info("dispatch audio sequence header success"); | 984 | srs_info("dispatch audio sequence header success"); |
| 935 | 985 | ||
| 986 | + // copy gop cache to client. | ||
| 936 | if ((ret = gop_cache->dump(consumer, sample_rate, frame_rate)) != ERROR_SUCCESS) { | 987 | if ((ret = gop_cache->dump(consumer, sample_rate, frame_rate)) != ERROR_SUCCESS) { |
| 937 | return ret; | 988 | return ret; |
| 938 | } | 989 | } |
| @@ -957,6 +1008,11 @@ void SrsSource::set_cache(bool enabled) | @@ -957,6 +1008,11 @@ void SrsSource::set_cache(bool enabled) | ||
| 957 | gop_cache->set(enabled); | 1008 | gop_cache->set(enabled); |
| 958 | } | 1009 | } |
| 959 | 1010 | ||
| 1011 | +bool SrsSource::is_atc() | ||
| 1012 | +{ | ||
| 1013 | + return atc; | ||
| 1014 | +} | ||
| 1015 | + | ||
| 960 | int SrsSource::create_forwarders() | 1016 | int SrsSource::create_forwarders() |
| 961 | { | 1017 | { |
| 962 | int ret = ERROR_SUCCESS; | 1018 | int ret = ERROR_SUCCESS; |
| @@ -191,6 +191,12 @@ public: | @@ -191,6 +191,12 @@ public: | ||
| 191 | virtual int cache(SrsSharedPtrMessage* msg); | 191 | virtual int cache(SrsSharedPtrMessage* msg); |
| 192 | virtual void clear(); | 192 | virtual void clear(); |
| 193 | virtual int dump(SrsConsumer* consumer, int tba, int tbv); | 193 | virtual int dump(SrsConsumer* consumer, int tba, int tbv); |
| 194 | + /** | ||
| 195 | + * used for atc to get the time of gop cache, | ||
| 196 | + * the atc will adjust the sequence header timestamp to gop cache. | ||
| 197 | + */ | ||
| 198 | + virtual bool empty(); | ||
| 199 | + virtual int64_t get_start_time(); | ||
| 194 | }; | 200 | }; |
| 195 | 201 | ||
| 196 | /** | 202 | /** |
| @@ -238,6 +244,13 @@ private: | @@ -238,6 +244,13 @@ private: | ||
| 238 | * can publish, true when is not streaming | 244 | * can publish, true when is not streaming |
| 239 | */ | 245 | */ |
| 240 | bool _can_publish; | 246 | bool _can_publish; |
| 247 | + /** | ||
| 248 | + * atc whether atc(use absolute time and donot adjust time), | ||
| 249 | + * directly use msg time and donot adjust if atc is true, | ||
| 250 | + * otherwise, adjust msg time to start from 0 to make flash happy. | ||
| 251 | + */ | ||
| 252 | + // TODO: FIXME: to support reload atc. | ||
| 253 | + bool atc; | ||
| 241 | private: | 254 | private: |
| 242 | SrsSharedPtrMessage* cache_metadata; | 255 | SrsSharedPtrMessage* cache_metadata; |
| 243 | // the cached video sequence header. | 256 | // the cached video sequence header. |
| @@ -279,6 +292,10 @@ public: | @@ -279,6 +292,10 @@ public: | ||
| 279 | virtual int create_consumer(SrsConsumer*& consumer); | 292 | virtual int create_consumer(SrsConsumer*& consumer); |
| 280 | virtual void on_consumer_destroy(SrsConsumer* consumer); | 293 | virtual void on_consumer_destroy(SrsConsumer* consumer); |
| 281 | virtual void set_cache(bool enabled); | 294 | virtual void set_cache(bool enabled); |
| 295 | +// internal | ||
| 296 | +public: | ||
| 297 | + // for consumer, atc feature. | ||
| 298 | + virtual bool is_atc(); | ||
| 282 | private: | 299 | private: |
| 283 | virtual int create_forwarders(); | 300 | virtual int create_forwarders(); |
| 284 | virtual void destroy_forwarders(); | 301 | virtual void destroy_forwarders(); |
| @@ -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 "34" | 34 | +#define VERSION_REVISION "35" |
| 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" |
| @@ -1163,7 +1163,7 @@ int SrsComplexHandshake::handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrs | @@ -1163,7 +1163,7 @@ int SrsComplexHandshake::handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrs | ||
| 1163 | // never verify c2, for ffmpeg will failed. | 1163 | // never verify c2, for ffmpeg will failed. |
| 1164 | // it's ok for flash. | 1164 | // it's ok for flash. |
| 1165 | 1165 | ||
| 1166 | - srs_trace("comple handshake with client success"); | 1166 | + srs_trace("complex handshake with client success"); |
| 1167 | 1167 | ||
| 1168 | return ret; | 1168 | return ret; |
| 1169 | } | 1169 | } |
-
请 注册 或 登录 后发表评论