winlin

Support RTMP ATC for HLS/HDS to support backup(failover). change to 0.9.35

@@ -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 }