winlin

for #293, add http flv stream

@@ -343,11 +343,11 @@ vhost ingest.srs.com { @@ -343,11 +343,11 @@ vhost ingest.srs.com {
343 } 343 }
344 } 344 }
345 345
346 -# vhost for http server config in each vhost.  
347 -vhost http.srs.com {  
348 - # http vhost specified config 346 +# vhost for http static and flv vod stream for each vhost.
  347 +vhost http.static.srs.com {
  348 + # http static vhost specified config
349 http { 349 http {
350 - # whether enabled the http streaming service for vhost. 350 + # whether enabled the http static service for vhost.
351 # default: off 351 # default: off
352 enabled on; 352 enabled on;
353 # the virtual directory root for this vhost to mount at 353 # the virtual directory root for this vhost to mount at
@@ -364,6 +364,24 @@ vhost http.srs.com { @@ -364,6 +364,24 @@ vhost http.srs.com {
364 } 364 }
365 } 365 }
366 366
  367 +# vhost for http flv live stream for each vhost.
  368 +vhost http.flv.srs.com {
  369 + # http flv stream vhost specified config
  370 + http_flv {
  371 + # whether enable the http flv live streaming service for vhost.
  372 + # default: off
  373 + enabled on;
  374 + # the stream mout for rtmp to remux to flv live streaming.
  375 + # for example, if mount to [vhost]/[app]/[stream].flv, user access by http://[vhost]/[app]/[stream].flv
  376 + # the variables:
  377 + # [vhost] current vhost for http flv live stream.
  378 + # [app] current app for http flv live stream.
  379 + # [stream] current stream for http flv live stream.
  380 + # default: [vhost]/[app]/[stream].flv
  381 + mount [vhost]/[app]/[stream].flv;
  382 + }
  383 +}
  384 +
367 # the vhost with hls specified. 385 # the vhost with hls specified.
368 vhost with-hls.srs.com { 386 vhost with-hls.srs.com {
369 hls { 387 hls {
  1 +# the config for srs to remux rtmp to flv live stream.
  2 +# @see https://github.com/winlinvip/simple-rtmp-server/wiki/v2_CN_DeliveryHttpFlvStream
  3 +# @see full.conf for detail config.
  4 +
  5 +listen 1935;
  6 +max_connections 1000;
  7 +http_stream {
  8 + enabled on;
  9 + listen 8080;
  10 + dir ./objs/nginx/html;
  11 +}
  12 +vhost __defaultVhost__ {
  13 + http_flv {
  14 + enabled on;
  15 + mount [vhost]/[app]/[stream].flv;
  16 + }
  17 +}
@@ -876,6 +876,17 @@ int SrsConfig::reload_vhost(SrsConfDirective* old_root) @@ -876,6 +876,17 @@ int SrsConfig::reload_vhost(SrsConfDirective* old_root)
876 } 876 }
877 srs_trace("vhost %s reload http success.", vhost.c_str()); 877 srs_trace("vhost %s reload http success.", vhost.c_str());
878 } 878 }
  879 + // http_flv, only one per vhost.
  880 + if (!srs_directive_equals(new_vhost->get("http_flv"), old_vhost->get("http_flv"))) {
  881 + for (it = subscribes.begin(); it != subscribes.end(); ++it) {
  882 + ISrsReloadHandler* subscribe = *it;
  883 + if ((ret = subscribe->on_reload_vhost_http_flv_updated()) != ERROR_SUCCESS) {
  884 + srs_error("vhost %s notify subscribes http_flv failed. ret=%d", vhost.c_str(), ret);
  885 + return ret;
  886 + }
  887 + }
  888 + srs_trace("vhost %s reload http_flv success.", vhost.c_str());
  889 + }
879 // transcode, many per vhost. 890 // transcode, many per vhost.
880 if ((ret = reload_transcode(new_vhost, old_vhost)) != ERROR_SUCCESS) { 891 if ((ret = reload_transcode(new_vhost, old_vhost)) != ERROR_SUCCESS) {
881 return ret; 892 return ret;
@@ -1364,7 +1375,7 @@ int SrsConfig::check_config() @@ -1364,7 +1375,7 @@ int SrsConfig::check_config()
1364 && n != "atc" && n != "atc_auto" 1375 && n != "atc" && n != "atc_auto"
1365 && n != "debug_srs_upnode" 1376 && n != "debug_srs_upnode"
1366 && n != "mr" && n != "mw_latency" && n != "min_latency" 1377 && n != "mr" && n != "mw_latency" && n != "min_latency"
1367 - && n != "security" 1378 + && n != "security" && n != "http_flv"
1368 ) { 1379 ) {
1369 ret = ERROR_SYSTEM_CONFIG_INVALID; 1380 ret = ERROR_SYSTEM_CONFIG_INVALID;
1370 srs_error("unsupported vhost directive %s, ret=%d", n.c_str(), ret); 1381 srs_error("unsupported vhost directive %s, ret=%d", n.c_str(), ret);
@@ -1412,6 +1423,15 @@ int SrsConfig::check_config() @@ -1412,6 +1423,15 @@ int SrsConfig::check_config()
1412 return ret; 1423 return ret;
1413 } 1424 }
1414 } 1425 }
  1426 + } else if (n == "http_flv") {
  1427 + for (int j = 0; j < (int)conf->directives.size(); j++) {
  1428 + string m = conf->at(j)->name.c_str();
  1429 + if (m != "enabled" && m != "mount") {
  1430 + ret = ERROR_SYSTEM_CONFIG_INVALID;
  1431 + srs_error("unsupported vhost http_flv directive %s, ret=%d", m.c_str(), ret);
  1432 + return ret;
  1433 + }
  1434 + }
1415 } else if (n == "hls") { 1435 } else if (n == "hls") {
1416 for (int j = 0; j < (int)conf->directives.size(); j++) { 1436 for (int j = 0; j < (int)conf->directives.size(); j++) {
1417 string m = conf->at(j)->name.c_str(); 1437 string m = conf->at(j)->name.c_str();
@@ -3425,6 +3445,50 @@ string SrsConfig::get_vhost_http_dir(string vhost) @@ -3425,6 +3445,50 @@ string SrsConfig::get_vhost_http_dir(string vhost)
3425 return conf->arg0(); 3445 return conf->arg0();
3426 } 3446 }
3427 3447
  3448 +bool SrsConfig::get_vhost_http_flv_enabled(string vhost)
  3449 +{
  3450 + SrsConfDirective* conf = get_vhost(vhost);
  3451 + if (!conf) {
  3452 + return false;
  3453 + }
  3454 +
  3455 + conf = conf->get("http_flv");
  3456 + if (!conf) {
  3457 + return false;
  3458 + }
  3459 +
  3460 + conf = conf->get("enabled");
  3461 + if (!conf) {
  3462 + return false;
  3463 + }
  3464 +
  3465 + if (conf->arg0() == "on") {
  3466 + return true;
  3467 + }
  3468 +
  3469 + return false;
  3470 +}
  3471 +
  3472 +string SrsConfig::get_vhost_http_flv_mount(string vhost)
  3473 +{
  3474 + SrsConfDirective* conf = get_vhost(vhost);
  3475 + if (!conf) {
  3476 + return SRS_CONF_DEFAULT_HTTP_FLV_MOUNT;
  3477 + }
  3478 +
  3479 + conf = conf->get("http_flv");
  3480 + if (!conf) {
  3481 + return SRS_CONF_DEFAULT_HTTP_FLV_MOUNT;
  3482 + }
  3483 +
  3484 + conf = conf->get("mount");
  3485 + if (!conf || conf->arg0().empty()) {
  3486 + return SRS_CONF_DEFAULT_HTTP_FLV_MOUNT;
  3487 + }
  3488 +
  3489 + return conf->arg0();
  3490 +}
  3491 +
3428 SrsConfDirective* SrsConfig::get_heartbeart() 3492 SrsConfDirective* SrsConfig::get_heartbeart()
3429 { 3493 {
3430 return root->get("heartbeat"); 3494 return root->get("heartbeat");
@@ -65,7 +65,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -65,7 +65,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
65 // the interval in seconds for bandwidth check 65 // the interval in seconds for bandwidth check
66 #define SRS_CONF_DEFAULT_BANDWIDTH_LIMIT_KBPS 1000 66 #define SRS_CONF_DEFAULT_BANDWIDTH_LIMIT_KBPS 1000
67 67
68 -#define SRS_CONF_DEFAULT_HTTP_MOUNT "/" 68 +#define SRS_CONF_DEFAULT_HTTP_MOUNT "[vhost]/"
  69 +#define SRS_CONF_DEFAULT_HTTP_FLV_MOUNT "[vhost]/[app]/[stream].flv"
69 #define SRS_CONF_DEFAULT_HTTP_DIR SRS_CONF_DEFAULT_HLS_PATH 70 #define SRS_CONF_DEFAULT_HTTP_DIR SRS_CONF_DEFAULT_HLS_PATH
70 71
71 #define SRS_CONF_DEFAULT_HTTP_STREAM_PORT 8080 72 #define SRS_CONF_DEFAULT_HTTP_STREAM_PORT 8080
@@ -954,20 +955,26 @@ public: @@ -954,20 +955,26 @@ public:
954 */ 955 */
955 virtual bool get_vhost_http_enabled(std::string vhost); 956 virtual bool get_vhost_http_enabled(std::string vhost);
956 /** 957 /**
957 - * get the http mount point for vhost,  
958 - * vhost can use sub dir of http.  
959 - * for example, http://server/vhost1/live/livestream  
960 - * where the vhost1 is mount point for vhost1. 958 + * get the http mount point for vhost.
  959 + * for example, http://vhost/live/livestream
961 */ 960 */
962 virtual std::string get_vhost_http_mount(std::string vhost); 961 virtual std::string get_vhost_http_mount(std::string vhost);
963 /** 962 /**
964 * get the http dir for vhost. 963 * get the http dir for vhost.
965 - * the http dir of vhost will mount to the mount point of vhost.  
966 - * for example, http://server/vhost1/live/livestream  
967 - * where the vhost1 is mount point for vhost1,  
968 - * and vhost1 dir is specified by this http dir. 964 + * the path on disk for mount root of http vhost.
969 */ 965 */
970 virtual std::string get_vhost_http_dir(std::string vhost); 966 virtual std::string get_vhost_http_dir(std::string vhost);
  967 +// flv live streaming section
  968 +public:
  969 + /**
  970 + * get whether vhost enabled http flv live stream
  971 + */
  972 + virtual bool get_vhost_http_flv_enabled(std::string vhost);
  973 + /**
  974 + * get the http flv live stream mount point for vhost.
  975 + * used to generate the flv stream mount path.
  976 + */
  977 + virtual std::string get_vhost_http_flv_mount(std::string vhost);
971 // http heartbeart section 978 // http heartbeart section
972 private: 979 private:
973 /** 980 /**
@@ -135,21 +135,69 @@ int SrsVodStream::serve_flv_stream(ISrsGoHttpResponseWriter* w, SrsHttpMessage* @@ -135,21 +135,69 @@ int SrsVodStream::serve_flv_stream(ISrsGoHttpResponseWriter* w, SrsHttpMessage*
135 return ret; 135 return ret;
136 } 136 }
137 137
  138 +SrsLiveStream::SrsLiveStream()
  139 +{
  140 +}
  141 +
  142 +SrsLiveStream::~SrsLiveStream()
  143 +{
  144 +}
  145 +
  146 +int SrsLiveStream::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
  147 +{
  148 + int ret = ERROR_SUCCESS;
  149 + // TODO: FIMXE: implements it.
  150 + return ret;
  151 +}
  152 +
138 SrsHttpServer::SrsHttpServer() 153 SrsHttpServer::SrsHttpServer()
139 { 154 {
140 } 155 }
141 156
142 SrsHttpServer::~SrsHttpServer() 157 SrsHttpServer::~SrsHttpServer()
143 { 158 {
  159 + flvs.clear();
144 } 160 }
145 161
146 int SrsHttpServer::initialize() 162 int SrsHttpServer::initialize()
147 { 163 {
148 int ret = ERROR_SUCCESS; 164 int ret = ERROR_SUCCESS;
149 165
  166 + // static file
  167 + // flv vod streaming.
  168 + if ((ret = mount_static_file()) != ERROR_SUCCESS) {
  169 + return ret;
  170 + }
  171 +
  172 + // remux rtmp to flv live streaming
  173 + if ((ret = mount_flv_streaming()) != ERROR_SUCCESS) {
  174 + return ret;
  175 + }
  176 +
  177 + return ret;
  178 +}
  179 +
  180 +int SrsHttpServer::on_reload_vhost_http_updated()
  181 +{
  182 + int ret = ERROR_SUCCESS;
  183 + // TODO: FIXME: implements it.
  184 + return ret;
  185 +}
  186 +
  187 +int SrsHttpServer::on_reload_vhost_http_flv_updated()
  188 +{
  189 + int ret = ERROR_SUCCESS;
  190 + // TODO: FIXME: implements it.
  191 + return ret;
  192 +}
  193 +
  194 +int SrsHttpServer::mount_static_file()
  195 +{
  196 + int ret = ERROR_SUCCESS;
  197 +
150 bool default_root_exists = false; 198 bool default_root_exists = false;
151 199
152 - // add other virtual path 200 + // http static file and flv vod stream mount for each vhost.
153 SrsConfDirective* root = _srs_config->get_root(); 201 SrsConfDirective* root = _srs_config->get_root();
154 for (int i = 0; i < (int)root->directives.size(); i++) { 202 for (int i = 0; i < (int)root->directives.size(); i++) {
155 SrsConfDirective* conf = root->at(i); 203 SrsConfDirective* conf = root->at(i);
@@ -169,6 +217,9 @@ int SrsHttpServer::initialize() @@ -169,6 +217,9 @@ int SrsHttpServer::initialize()
169 // replace the vhost variable 217 // replace the vhost variable
170 mount = srs_string_replace(mount, "[vhost]", vhost); 218 mount = srs_string_replace(mount, "[vhost]", vhost);
171 219
  220 + // remove the default vhost mount
  221 + mount = srs_string_replace(mount, SRS_CONSTS_RTMP_DEFAULT_VHOST"/", "");
  222 +
172 // the dir mount must always ends with "/" 223 // the dir mount must always ends with "/"
173 if (mount != "/" && mount.rfind("/") != mount.length() - 1) { 224 if (mount != "/" && mount.rfind("/") != mount.length() - 1) {
174 mount += "/"; 225 mount += "/";
@@ -199,10 +250,30 @@ int SrsHttpServer::initialize() @@ -199,10 +250,30 @@ int SrsHttpServer::initialize()
199 return ret; 250 return ret;
200 } 251 }
201 252
202 -int SrsHttpServer::on_reload_vhost_http_updated() 253 +int SrsHttpServer::mount_flv_streaming()
203 { 254 {
204 int ret = ERROR_SUCCESS; 255 int ret = ERROR_SUCCESS;
205 - // TODO: FIXME: implements it. 256 +
  257 + // http flv live stream mount for each vhost.
  258 + SrsConfDirective* root = _srs_config->get_root();
  259 + for (int i = 0; i < (int)root->directives.size(); i++) {
  260 + SrsConfDirective* conf = root->at(i);
  261 +
  262 + if (!conf->is_vhost()) {
  263 + continue;
  264 + }
  265 +
  266 + std::string vhost = conf->arg0();
  267 + if (!_srs_config->get_vhost_http_flv_enabled(vhost)) {
  268 + continue;
  269 + }
  270 +
  271 + std::string mount = _srs_config->get_vhost_http_flv_mount(vhost);
  272 + flvs[vhost] = mount;
  273 + srs_trace("http flv live stream, vhost=%s, mount=%s",
  274 + vhost.c_str(), mount.c_str());
  275 + }
  276 +
206 return ret; 277 return ret;
207 } 278 }
208 279
@@ -57,10 +57,29 @@ protected: @@ -57,10 +57,29 @@ protected:
57 virtual int serve_flv_stream(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath, int offset); 57 virtual int serve_flv_stream(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath, int offset);
58 }; 58 };
59 59
  60 +/**
  61 +* the flv live stream supports access rtmp in flv over http.
  62 +* srs will remux rtmp to flv streaming.
  63 +*/
  64 +class SrsLiveStream : public ISrsGoHttpHandler
  65 +{
  66 +public:
  67 + SrsLiveStream();
  68 + virtual ~SrsLiveStream();
  69 +public:
  70 + virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r);
  71 +};
  72 +
  73 +/**
  74 +* the http server instance,
  75 +* serve http static file, flv vod stream and flv live stream.
  76 +*/
60 class SrsHttpServer : public ISrsReloadHandler 77 class SrsHttpServer : public ISrsReloadHandler
61 { 78 {
62 public: 79 public:
63 SrsGoHttpServeMux mux; 80 SrsGoHttpServeMux mux;
  81 + // the flv live streaming template.
  82 + std::map<std::string, std::string> flvs;
64 public: 83 public:
65 SrsHttpServer(); 84 SrsHttpServer();
66 virtual ~SrsHttpServer(); 85 virtual ~SrsHttpServer();
@@ -69,6 +88,10 @@ public: @@ -69,6 +88,10 @@ public:
69 // interface ISrsThreadHandler. 88 // interface ISrsThreadHandler.
70 public: 89 public:
71 virtual int on_reload_vhost_http_updated(); 90 virtual int on_reload_vhost_http_updated();
  91 + virtual int on_reload_vhost_http_flv_updated();
  92 +private:
  93 + virtual int mount_static_file();
  94 + virtual int mount_flv_streaming();
72 }; 95 };
73 96
74 class SrsHttpConn : public SrsConnection 97 class SrsHttpConn : public SrsConnection
@@ -95,6 +95,11 @@ int ISrsReloadHandler::on_reload_vhost_http_updated() @@ -95,6 +95,11 @@ int ISrsReloadHandler::on_reload_vhost_http_updated()
95 return ERROR_SUCCESS; 95 return ERROR_SUCCESS;
96 } 96 }
97 97
  98 +int ISrsReloadHandler::on_reload_vhost_http_flv_updated()
  99 +{
  100 + return ERROR_SUCCESS;
  101 +}
  102 +
98 int ISrsReloadHandler::on_reload_vhost_added(string /*vhost*/) 103 int ISrsReloadHandler::on_reload_vhost_added(string /*vhost*/)
99 { 104 {
100 return ERROR_SUCCESS; 105 return ERROR_SUCCESS;
@@ -56,6 +56,7 @@ public: @@ -56,6 +56,7 @@ public:
56 virtual int on_reload_http_stream_disabled(); 56 virtual int on_reload_http_stream_disabled();
57 virtual int on_reload_http_stream_updated(); 57 virtual int on_reload_http_stream_updated();
58 virtual int on_reload_vhost_http_updated(); 58 virtual int on_reload_vhost_http_updated();
  59 + virtual int on_reload_vhost_http_flv_updated();
59 virtual int on_reload_vhost_added(std::string vhost); 60 virtual int on_reload_vhost_added(std::string vhost);
60 virtual int on_reload_vhost_removed(std::string vhost); 61 virtual int on_reload_vhost_removed(std::string vhost);
61 virtual int on_reload_vhost_atc(std::string vhost); 62 virtual int on_reload_vhost_atc(std::string vhost);