mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
Support RTMP ATC for HLS/HDS to support backup(failover). change to 0.9.35
This commit is contained in:
parent
ebf1139582
commit
0858bd8b6f
8 changed files with 120 additions and 13 deletions
14
README.md
14
README.md
|
@ -112,13 +112,13 @@ Supported operating systems and hardware:
|
||||||
26. Support RTMP(play-publish) library: srs-librtmp<br/>
|
26. Support RTMP(play-publish) library: srs-librtmp<br/>
|
||||||
27. Support ARM([debian armhf, v7cpu](https://github.com/winlinvip/simple-rtmp-server/wiki/SrsLinuxArm)) with rtmp/ssl/hls/librtmp.<br/>
|
27. Support ARM([debian armhf, v7cpu](https://github.com/winlinvip/simple-rtmp-server/wiki/SrsLinuxArm)) with rtmp/ssl/hls/librtmp.<br/>
|
||||||
28. Support [init.d](https://github.com/winlinvip/simple-rtmp-server/wiki/LinuxService) and packge script, log to file. <br/>
|
28. Support [init.d](https://github.com/winlinvip/simple-rtmp-server/wiki/LinuxService) and packge script, log to file. <br/>
|
||||||
29. [plan] Support system utest<br/>
|
29. Support RTMP ATC for HLS/HDS to support backup(failover)<br/>
|
||||||
30. [plan] Support embeded http server for api and hls(live/vod)<br/>
|
30. [plan] Support system utest<br/>
|
||||||
31. [plan] Support vod(file to hls stream)<br/>
|
31. [plan] Support embeded http server for api and hls(live/vod)<br/>
|
||||||
32. [plan] Support stream ingester using ffmpeg.<br/>
|
32. [plan] Support vod(file to hls stream)<br/>
|
||||||
33. [plan] Support ingest RTSP(RTP, SDP) stream to RTMP.<br/>
|
33. [plan] Support stream ingester using ffmpeg.<br/>
|
||||||
34. [plan] Support network based cli and json result.<br/>
|
34. [plan] Support ingest RTSP(RTP, SDP) stream to RTMP.<br/>
|
||||||
35. [plan] Support HLS cluster, use RTMP ATC to generate the TS<br/>
|
35. [plan] Support network based cli and json result.<br/>
|
||||||
36. [plan] Support RTMP edge server, push/pull stream from any RTMP server<br/>
|
36. [plan] Support RTMP edge server, push/pull stream from any RTMP server<br/>
|
||||||
37. [plan] Support multiple processes, for both origin and edge<br/>
|
37. [plan] Support multiple processes, for both origin and edge<br/>
|
||||||
38. [no-plan] Support adobe flash refer/token/swf verification.<br/>
|
38. [no-plan] Support adobe flash refer/token/swf verification.<br/>
|
||||||
|
|
|
@ -41,6 +41,23 @@ vhost __defaultVhost__ {
|
||||||
gop_cache on;
|
gop_cache on;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# vhost for atc.
|
||||||
|
vhost atc.srs.com {
|
||||||
|
# vhost for atc for hls/hds/rtmp backup.
|
||||||
|
# generally, atc default to off, server delivery rtmp stream to client(flash) timestamp from 0.
|
||||||
|
# when atc is on, server delivery rtmp stream by absolute time.
|
||||||
|
# atc is used, for instance, encoder will copy stream to master and slave server,
|
||||||
|
# server use atc to delivery stream to edge/client, where stream time from master/slave server
|
||||||
|
# is always the same, client/tools can slice RTMP stream to HLS according to the same time,
|
||||||
|
# if the time not the same, the HLS stream cannot slice to support system backup.
|
||||||
|
#
|
||||||
|
# @see http://www.adobe.com/cn/devnet/adobe-media-server/articles/varnish-sample-for-failover.html
|
||||||
|
# @see http://www.baidu.com/#wd=hds%20hls%20atc
|
||||||
|
#
|
||||||
|
# default: off
|
||||||
|
atc on;
|
||||||
|
}
|
||||||
|
|
||||||
# vhost for bandwidth check
|
# vhost for bandwidth check
|
||||||
# generally, the bandcheck vhost must be: bandcheck.srs.com,
|
# generally, the bandcheck vhost must be: bandcheck.srs.com,
|
||||||
# or need to modify the vhost of client.
|
# or need to modify the vhost of client.
|
||||||
|
|
|
@ -1340,6 +1340,22 @@ bool SrsConfig::get_gop_cache(string vhost)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SrsConfig::get_atc(string vhost)
|
||||||
|
{
|
||||||
|
SrsConfDirective* conf = get_vhost(vhost);
|
||||||
|
|
||||||
|
if (!conf) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
conf = conf->get("atc");
|
||||||
|
if (conf && conf->arg0() == "on") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
double SrsConfig::get_queue_length(string vhost)
|
double SrsConfig::get_queue_length(string vhost)
|
||||||
{
|
{
|
||||||
SrsConfDirective* conf = get_vhost(vhost);
|
SrsConfDirective* conf = get_vhost(vhost);
|
||||||
|
|
|
@ -153,6 +153,7 @@ public:
|
||||||
virtual bool get_deamon();
|
virtual bool get_deamon();
|
||||||
virtual int get_max_connections();
|
virtual int get_max_connections();
|
||||||
virtual bool get_gop_cache(std::string vhost);
|
virtual bool get_gop_cache(std::string vhost);
|
||||||
|
virtual bool get_atc(std::string vhost);
|
||||||
virtual double get_queue_length(std::string vhost);
|
virtual double get_queue_length(std::string vhost);
|
||||||
virtual SrsConfDirective* get_forward(std::string vhost);
|
virtual SrsConfDirective* get_forward(std::string vhost);
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -268,11 +268,12 @@ int SrsConsumer::enqueue(SrsSharedPtrMessage* msg, int tba, int tbv)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
/* TODO: to support atc */
|
if (!source->is_atc()) {
|
||||||
if ((ret = jitter->correct(msg, tba, tbv)) != ERROR_SUCCESS) {
|
if ((ret = jitter->correct(msg, tba, tbv)) != ERROR_SUCCESS) {
|
||||||
srs_freep(msg);
|
srs_freep(msg);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) {
|
if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -391,6 +392,23 @@ int SrsGopCache::dump(SrsConsumer* consumer, int tba, int tbv)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SrsGopCache::empty()
|
||||||
|
{
|
||||||
|
return gop_cache.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t SrsGopCache::get_start_time()
|
||||||
|
{
|
||||||
|
if (empty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsSharedPtrMessage* msg = gop_cache[0];
|
||||||
|
srs_assert(msg);
|
||||||
|
|
||||||
|
return msg->header.timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
std::map<std::string, SrsSource*> SrsSource::pool;
|
std::map<std::string, SrsSource*> SrsSource::pool;
|
||||||
|
|
||||||
SrsSource* SrsSource::find(SrsRequest* req)
|
SrsSource* SrsSource::find(SrsRequest* req)
|
||||||
|
@ -425,6 +443,7 @@ SrsSource::SrsSource(SrsRequest* _req)
|
||||||
gop_cache = new SrsGopCache();
|
gop_cache = new SrsGopCache();
|
||||||
|
|
||||||
_srs_config->subscribe(this);
|
_srs_config->subscribe(this);
|
||||||
|
atc = _srs_config->get_atc(req->vhost);
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsSource::~SrsSource()
|
SrsSource::~SrsSource()
|
||||||
|
@ -774,6 +793,16 @@ int SrsSource::on_audio(SrsCommonMessage* audio)
|
||||||
}
|
}
|
||||||
srs_verbose("cache gop success.");
|
srs_verbose("cache gop success.");
|
||||||
|
|
||||||
|
// if atc, update the sequence header to abs time.
|
||||||
|
if (atc) {
|
||||||
|
if (cache_sh_audio) {
|
||||||
|
cache_sh_audio->header.timestamp = msg->header.timestamp;
|
||||||
|
}
|
||||||
|
if (cache_metadata) {
|
||||||
|
cache_metadata->header.timestamp = msg->header.timestamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -841,6 +870,16 @@ int SrsSource::on_video(SrsCommonMessage* video)
|
||||||
}
|
}
|
||||||
srs_verbose("cache gop success.");
|
srs_verbose("cache gop success.");
|
||||||
|
|
||||||
|
// if atc, update the sequence header to abs time.
|
||||||
|
if (atc) {
|
||||||
|
if (cache_sh_video) {
|
||||||
|
cache_sh_video->header.timestamp = msg->header.timestamp;
|
||||||
|
}
|
||||||
|
if (cache_metadata) {
|
||||||
|
cache_metadata->header.timestamp = msg->header.timestamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -921,6 +960,17 @@ void SrsSource::on_unpublish()
|
||||||
}
|
}
|
||||||
srs_info("dispatch metadata success");
|
srs_info("dispatch metadata success");
|
||||||
|
|
||||||
|
// if atc, update the sequence header to gop cache time.
|
||||||
|
if (atc && !gop_cache->empty()) {
|
||||||
|
if (cache_sh_video) {
|
||||||
|
cache_sh_video->header.timestamp = gop_cache->get_start_time();
|
||||||
|
}
|
||||||
|
if (cache_sh_audio) {
|
||||||
|
cache_sh_audio->header.timestamp = gop_cache->get_start_time();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy sequence header
|
||||||
if (cache_sh_video && (ret = consumer->enqueue(cache_sh_video->copy(), sample_rate, frame_rate)) != ERROR_SUCCESS) {
|
if (cache_sh_video && (ret = consumer->enqueue(cache_sh_video->copy(), sample_rate, frame_rate)) != ERROR_SUCCESS) {
|
||||||
srs_error("dispatch video sequence header failed. ret=%d", ret);
|
srs_error("dispatch video sequence header failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -933,6 +983,7 @@ void SrsSource::on_unpublish()
|
||||||
}
|
}
|
||||||
srs_info("dispatch audio sequence header success");
|
srs_info("dispatch audio sequence header success");
|
||||||
|
|
||||||
|
// copy gop cache to client.
|
||||||
if ((ret = gop_cache->dump(consumer, sample_rate, frame_rate)) != ERROR_SUCCESS) {
|
if ((ret = gop_cache->dump(consumer, sample_rate, frame_rate)) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -957,6 +1008,11 @@ void SrsSource::set_cache(bool enabled)
|
||||||
gop_cache->set(enabled);
|
gop_cache->set(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SrsSource::is_atc()
|
||||||
|
{
|
||||||
|
return atc;
|
||||||
|
}
|
||||||
|
|
||||||
int SrsSource::create_forwarders()
|
int SrsSource::create_forwarders()
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
|
@ -191,6 +191,12 @@ public:
|
||||||
virtual int cache(SrsSharedPtrMessage* msg);
|
virtual int cache(SrsSharedPtrMessage* msg);
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
virtual int dump(SrsConsumer* consumer, int tba, int tbv);
|
virtual int dump(SrsConsumer* consumer, int tba, int tbv);
|
||||||
|
/**
|
||||||
|
* used for atc to get the time of gop cache,
|
||||||
|
* the atc will adjust the sequence header timestamp to gop cache.
|
||||||
|
*/
|
||||||
|
virtual bool empty();
|
||||||
|
virtual int64_t get_start_time();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -238,6 +244,13 @@ private:
|
||||||
* can publish, true when is not streaming
|
* can publish, true when is not streaming
|
||||||
*/
|
*/
|
||||||
bool _can_publish;
|
bool _can_publish;
|
||||||
|
/**
|
||||||
|
* atc whether atc(use absolute time and donot adjust time),
|
||||||
|
* directly use msg time and donot adjust if atc is true,
|
||||||
|
* otherwise, adjust msg time to start from 0 to make flash happy.
|
||||||
|
*/
|
||||||
|
// TODO: FIXME: to support reload atc.
|
||||||
|
bool atc;
|
||||||
private:
|
private:
|
||||||
SrsSharedPtrMessage* cache_metadata;
|
SrsSharedPtrMessage* cache_metadata;
|
||||||
// the cached video sequence header.
|
// the cached video sequence header.
|
||||||
|
@ -279,6 +292,10 @@ public:
|
||||||
virtual int create_consumer(SrsConsumer*& consumer);
|
virtual int create_consumer(SrsConsumer*& consumer);
|
||||||
virtual void on_consumer_destroy(SrsConsumer* consumer);
|
virtual void on_consumer_destroy(SrsConsumer* consumer);
|
||||||
virtual void set_cache(bool enabled);
|
virtual void set_cache(bool enabled);
|
||||||
|
// internal
|
||||||
|
public:
|
||||||
|
// for consumer, atc feature.
|
||||||
|
virtual bool is_atc();
|
||||||
private:
|
private:
|
||||||
virtual int create_forwarders();
|
virtual int create_forwarders();
|
||||||
virtual void destroy_forwarders();
|
virtual void destroy_forwarders();
|
||||||
|
|
|
@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
// current release version
|
// current release version
|
||||||
#define VERSION_MAJOR "0"
|
#define VERSION_MAJOR "0"
|
||||||
#define VERSION_MINOR "9"
|
#define VERSION_MINOR "9"
|
||||||
#define VERSION_REVISION "34"
|
#define VERSION_REVISION "35"
|
||||||
#define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION
|
#define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION
|
||||||
// server info.
|
// server info.
|
||||||
#define RTMP_SIG_SRS_KEY "srs"
|
#define RTMP_SIG_SRS_KEY "srs"
|
||||||
|
|
|
@ -1163,7 +1163,7 @@ int SrsComplexHandshake::handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrs
|
||||||
// never verify c2, for ffmpeg will failed.
|
// never verify c2, for ffmpeg will failed.
|
||||||
// it's ok for flash.
|
// it's ok for flash.
|
||||||
|
|
||||||
srs_trace("comple handshake with client success");
|
srs_trace("complex handshake with client success");
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue