winlin

listen and serve stream caster mpegts over udp.

@@ -323,6 +323,12 @@ else @@ -323,6 +323,12 @@ else
323 echo "#undef SRS_AUTO_HTTP_SERVER" >> $SRS_AUTO_HEADERS_H 323 echo "#undef SRS_AUTO_HTTP_SERVER" >> $SRS_AUTO_HEADERS_H
324 fi 324 fi
325 325
  326 +if [ $SRS_STREAM_CASTER = YES ]; then
  327 + echo "#define SRS_AUTO_STREAM_CASTER" >> $SRS_AUTO_HEADERS_H
  328 +else
  329 + echo "#undef SRS_AUTO_STREAM_CASTER" >> $SRS_AUTO_HEADERS_H
  330 +fi
  331 +
326 if [ $SRS_HTTP_API = YES ]; then 332 if [ $SRS_HTTP_API = YES ]; then
327 echo "#define SRS_AUTO_HTTP_API" >> $SRS_AUTO_HEADERS_H 333 echo "#define SRS_AUTO_HTTP_API" >> $SRS_AUTO_HEADERS_H
328 else 334 else
@@ -25,6 +25,7 @@ SRS_INGEST=RESERVED @@ -25,6 +25,7 @@ SRS_INGEST=RESERVED
25 SRS_STAT=RESERVED 25 SRS_STAT=RESERVED
26 SRS_HTTP_CALLBACK=RESERVED 26 SRS_HTTP_CALLBACK=RESERVED
27 SRS_HTTP_SERVER=RESERVED 27 SRS_HTTP_SERVER=RESERVED
  28 +SRS_STREAM_CASTER=RESERVED
28 SRS_HTTP_API=RESERVED 29 SRS_HTTP_API=RESERVED
29 SRS_LIBRTMP=RESERVED 30 SRS_LIBRTMP=RESERVED
30 SRS_RESEARCH=RESERVED 31 SRS_RESEARCH=RESERVED
@@ -114,6 +115,7 @@ Options: @@ -114,6 +115,7 @@ Options:
114 build nginx at: ./objs/nginx/sbin/nginx 115 build nginx at: ./objs/nginx/sbin/nginx
115 --with-http-callback enable http hooks, build cherrypy as demo api server. 116 --with-http-callback enable http hooks, build cherrypy as demo api server.
116 --with-http-server enable http server to delivery http stream. 117 --with-http-server enable http server to delivery http stream.
  118 + --with-stream-caster enable stream caster to serve other stream over other protocol.
117 --with-http-api enable http api, to manage SRS by http api. 119 --with-http-api enable http api, to manage SRS by http api.
118 --with-ffmpeg enable transcoding tool ffmpeg. 120 --with-ffmpeg enable transcoding tool ffmpeg.
119 build ffmpeg at: ./objs/ffmpeg/bin/ffmpeg 121 build ffmpeg at: ./objs/ffmpeg/bin/ffmpeg
@@ -138,6 +140,7 @@ Options: @@ -138,6 +140,7 @@ Options:
138 --without-nginx disable delivery HTTP stream with nginx. 140 --without-nginx disable delivery HTTP stream with nginx.
139 --without-http-callback disable http, http hooks callback. 141 --without-http-callback disable http, http hooks callback.
140 --without-http-server disable http server, use external server to delivery http stream. 142 --without-http-server disable http server, use external server to delivery http stream.
  143 + --without-stream-caster disable stream caster, only listen and serve RTMP/HTTP.
141 --without-http-api disable http api, only use console to manage SRS process. 144 --without-http-api disable http api, only use console to manage SRS process.
142 --without-ffmpeg disable the ffmpeg transcode tool feature. 145 --without-ffmpeg disable the ffmpeg transcode tool feature.
143 --without-transcode disable the transcoding feature. 146 --without-transcode disable the transcoding feature.
@@ -213,6 +216,7 @@ function parse_user_option() { @@ -213,6 +216,7 @@ function parse_user_option() {
213 --with-stat) SRS_STAT=YES ;; 216 --with-stat) SRS_STAT=YES ;;
214 --with-http-callback) SRS_HTTP_CALLBACK=YES ;; 217 --with-http-callback) SRS_HTTP_CALLBACK=YES ;;
215 --with-http-server) SRS_HTTP_SERVER=YES ;; 218 --with-http-server) SRS_HTTP_SERVER=YES ;;
  219 + --with-stream-caster) SRS_STREAM_CASTER=YES ;;
216 --with-http-api) SRS_HTTP_API=YES ;; 220 --with-http-api) SRS_HTTP_API=YES ;;
217 --with-librtmp) SRS_LIBRTMP=YES ;; 221 --with-librtmp) SRS_LIBRTMP=YES ;;
218 --with-research) SRS_RESEARCH=YES ;; 222 --with-research) SRS_RESEARCH=YES ;;
@@ -235,6 +239,7 @@ function parse_user_option() { @@ -235,6 +239,7 @@ function parse_user_option() {
235 --without-stat) SRS_STAT=NO ;; 239 --without-stat) SRS_STAT=NO ;;
236 --without-http-callback) SRS_HTTP_CALLBACK=NO ;; 240 --without-http-callback) SRS_HTTP_CALLBACK=NO ;;
237 --without-http-server) SRS_HTTP_SERVER=NO ;; 241 --without-http-server) SRS_HTTP_SERVER=NO ;;
  242 + --without-stream-caster) SRS_STREAM_CASTER=NO ;;
238 --without-http-api) SRS_HTTP_API=NO ;; 243 --without-http-api) SRS_HTTP_API=NO ;;
239 --without-librtmp) SRS_LIBRTMP=NO ;; 244 --without-librtmp) SRS_LIBRTMP=NO ;;
240 --without-research) SRS_RESEARCH=NO ;; 245 --without-research) SRS_RESEARCH=NO ;;
@@ -362,6 +367,7 @@ function apply_user_presets() { @@ -362,6 +367,7 @@ function apply_user_presets() {
362 SRS_HTTP_PARSER=NO 367 SRS_HTTP_PARSER=NO
363 SRS_HTTP_CALLBACK=NO 368 SRS_HTTP_CALLBACK=NO
364 SRS_HTTP_SERVER=NO 369 SRS_HTTP_SERVER=NO
  370 + SRS_STREAM_CASTER=NO
365 SRS_HTTP_API=NO 371 SRS_HTTP_API=NO
366 SRS_LIBRTMP=NO 372 SRS_LIBRTMP=NO
367 SRS_RESEARCH=NO 373 SRS_RESEARCH=NO
@@ -387,6 +393,7 @@ function apply_user_presets() { @@ -387,6 +393,7 @@ function apply_user_presets() {
387 SRS_HTTP_PARSER=YES 393 SRS_HTTP_PARSER=YES
388 SRS_HTTP_CALLBACK=YES 394 SRS_HTTP_CALLBACK=YES
389 SRS_HTTP_SERVER=YES 395 SRS_HTTP_SERVER=YES
  396 + SRS_STREAM_CASTER=YES
390 SRS_HTTP_API=YES 397 SRS_HTTP_API=YES
391 SRS_LIBRTMP=YES 398 SRS_LIBRTMP=YES
392 SRS_RESEARCH=YES 399 SRS_RESEARCH=YES
@@ -412,6 +419,7 @@ function apply_user_presets() { @@ -412,6 +419,7 @@ function apply_user_presets() {
412 SRS_HTTP_PARSER=NO 419 SRS_HTTP_PARSER=NO
413 SRS_HTTP_CALLBACK=NO 420 SRS_HTTP_CALLBACK=NO
414 SRS_HTTP_SERVER=NO 421 SRS_HTTP_SERVER=NO
  422 + SRS_STREAM_CASTER=NO
415 SRS_HTTP_API=NO 423 SRS_HTTP_API=NO
416 SRS_LIBRTMP=NO 424 SRS_LIBRTMP=NO
417 SRS_RESEARCH=NO 425 SRS_RESEARCH=NO
@@ -437,6 +445,7 @@ function apply_user_presets() { @@ -437,6 +445,7 @@ function apply_user_presets() {
437 SRS_HTTP_PARSER=NO 445 SRS_HTTP_PARSER=NO
438 SRS_HTTP_CALLBACK=NO 446 SRS_HTTP_CALLBACK=NO
439 SRS_HTTP_SERVER=NO 447 SRS_HTTP_SERVER=NO
  448 + SRS_STREAM_CASTER=NO
440 SRS_HTTP_API=NO 449 SRS_HTTP_API=NO
441 SRS_LIBRTMP=NO 450 SRS_LIBRTMP=NO
442 SRS_RESEARCH=NO 451 SRS_RESEARCH=NO
@@ -462,6 +471,7 @@ function apply_user_presets() { @@ -462,6 +471,7 @@ function apply_user_presets() {
462 SRS_HTTP_PARSER=NO 471 SRS_HTTP_PARSER=NO
463 SRS_HTTP_CALLBACK=NO 472 SRS_HTTP_CALLBACK=NO
464 SRS_HTTP_SERVER=NO 473 SRS_HTTP_SERVER=NO
  474 + SRS_STREAM_CASTER=NO
465 SRS_HTTP_API=NO 475 SRS_HTTP_API=NO
466 SRS_LIBRTMP=NO 476 SRS_LIBRTMP=NO
467 SRS_RESEARCH=NO 477 SRS_RESEARCH=NO
@@ -487,6 +497,7 @@ function apply_user_presets() { @@ -487,6 +497,7 @@ function apply_user_presets() {
487 SRS_HTTP_PARSER=YES 497 SRS_HTTP_PARSER=YES
488 SRS_HTTP_CALLBACK=YES 498 SRS_HTTP_CALLBACK=YES
489 SRS_HTTP_SERVER=YES 499 SRS_HTTP_SERVER=YES
  500 + SRS_STREAM_CASTER=YES
490 SRS_HTTP_API=YES 501 SRS_HTTP_API=YES
491 SRS_LIBRTMP=YES 502 SRS_LIBRTMP=YES
492 SRS_RESEARCH=NO 503 SRS_RESEARCH=NO
@@ -513,6 +524,7 @@ function apply_user_presets() { @@ -513,6 +524,7 @@ function apply_user_presets() {
513 SRS_HTTP_PARSER=YES 524 SRS_HTTP_PARSER=YES
514 SRS_HTTP_CALLBACK=YES 525 SRS_HTTP_CALLBACK=YES
515 SRS_HTTP_SERVER=YES 526 SRS_HTTP_SERVER=YES
  527 + SRS_STREAM_CASTER=YES
516 SRS_HTTP_API=YES 528 SRS_HTTP_API=YES
517 SRS_LIBRTMP=YES 529 SRS_LIBRTMP=YES
518 SRS_RESEARCH=NO 530 SRS_RESEARCH=NO
@@ -538,6 +550,7 @@ function apply_user_presets() { @@ -538,6 +550,7 @@ function apply_user_presets() {
538 SRS_HTTP_PARSER=YES 550 SRS_HTTP_PARSER=YES
539 SRS_HTTP_CALLBACK=YES 551 SRS_HTTP_CALLBACK=YES
540 SRS_HTTP_SERVER=YES 552 SRS_HTTP_SERVER=YES
  553 + SRS_STREAM_CASTER=YES
541 SRS_HTTP_API=YES 554 SRS_HTTP_API=YES
542 SRS_LIBRTMP=YES 555 SRS_LIBRTMP=YES
543 SRS_RESEARCH=NO 556 SRS_RESEARCH=NO
@@ -563,6 +576,7 @@ function apply_user_presets() { @@ -563,6 +576,7 @@ function apply_user_presets() {
563 SRS_HTTP_PARSER=YES 576 SRS_HTTP_PARSER=YES
564 SRS_HTTP_CALLBACK=YES 577 SRS_HTTP_CALLBACK=YES
565 SRS_HTTP_SERVER=YES 578 SRS_HTTP_SERVER=YES
  579 + SRS_STREAM_CASTER=YES
566 SRS_HTTP_API=YES 580 SRS_HTTP_API=YES
567 SRS_LIBRTMP=YES 581 SRS_LIBRTMP=YES
568 SRS_RESEARCH=YES 582 SRS_RESEARCH=YES
@@ -588,6 +602,7 @@ function apply_user_presets() { @@ -588,6 +602,7 @@ function apply_user_presets() {
588 SRS_HTTP_PARSER=YES 602 SRS_HTTP_PARSER=YES
589 SRS_HTTP_CALLBACK=YES 603 SRS_HTTP_CALLBACK=YES
590 SRS_HTTP_SERVER=YES 604 SRS_HTTP_SERVER=YES
  605 + SRS_STREAM_CASTER=YES
591 SRS_HTTP_API=YES 606 SRS_HTTP_API=YES
592 SRS_LIBRTMP=NO 607 SRS_LIBRTMP=NO
593 SRS_RESEARCH=NO 608 SRS_RESEARCH=NO
@@ -613,6 +628,7 @@ function apply_user_presets() { @@ -613,6 +628,7 @@ function apply_user_presets() {
613 SRS_HTTP_PARSER=YES 628 SRS_HTTP_PARSER=YES
614 SRS_HTTP_CALLBACK=YES 629 SRS_HTTP_CALLBACK=YES
615 SRS_HTTP_SERVER=YES 630 SRS_HTTP_SERVER=YES
  631 + SRS_STREAM_CASTER=YES
616 SRS_HTTP_API=YES 632 SRS_HTTP_API=YES
617 SRS_LIBRTMP=YES 633 SRS_LIBRTMP=YES
618 SRS_RESEARCH=NO 634 SRS_RESEARCH=NO
@@ -638,6 +654,7 @@ function apply_user_presets() { @@ -638,6 +654,7 @@ function apply_user_presets() {
638 SRS_HTTP_PARSER=YES 654 SRS_HTTP_PARSER=YES
639 SRS_HTTP_CALLBACK=YES 655 SRS_HTTP_CALLBACK=YES
640 SRS_HTTP_SERVER=YES 656 SRS_HTTP_SERVER=YES
  657 + SRS_STREAM_CASTER=YES
641 SRS_HTTP_API=YES 658 SRS_HTTP_API=YES
642 SRS_LIBRTMP=YES 659 SRS_LIBRTMP=YES
643 SRS_RESEARCH=NO 660 SRS_RESEARCH=NO
@@ -663,6 +680,7 @@ function apply_user_presets() { @@ -663,6 +680,7 @@ function apply_user_presets() {
663 SRS_HTTP_PARSER=YES 680 SRS_HTTP_PARSER=YES
664 SRS_HTTP_CALLBACK=YES 681 SRS_HTTP_CALLBACK=YES
665 SRS_HTTP_SERVER=YES 682 SRS_HTTP_SERVER=YES
  683 + SRS_STREAM_CASTER=YES
666 SRS_HTTP_API=YES 684 SRS_HTTP_API=YES
667 SRS_LIBRTMP=YES 685 SRS_LIBRTMP=YES
668 SRS_RESEARCH=NO 686 SRS_RESEARCH=NO
@@ -723,6 +741,7 @@ function apply_user_detail_options() { @@ -723,6 +741,7 @@ function apply_user_detail_options() {
723 SRS_HTTP_PARSER=NO 741 SRS_HTTP_PARSER=NO
724 SRS_HTTP_CALLBACK=NO 742 SRS_HTTP_CALLBACK=NO
725 SRS_HTTP_SERVER=NO 743 SRS_HTTP_SERVER=NO
  744 + SRS_STREAM_CASTER=NO
726 SRS_HTTP_API=NO 745 SRS_HTTP_API=NO
727 SRS_LIBRTMP=YES 746 SRS_LIBRTMP=YES
728 SRS_RESEARCH=YES 747 SRS_RESEARCH=YES
@@ -752,6 +771,7 @@ function regenerate_options() { @@ -752,6 +771,7 @@ function regenerate_options() {
752 if [ $SRS_STAT = YES ]; then SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --with-stat"; else SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --without-stat"; fi 771 if [ $SRS_STAT = YES ]; then SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --with-stat"; else SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --without-stat"; fi
753 if [ $SRS_HTTP_CALLBACK = YES ]; then SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --with-http-callback"; else SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --without-http-callback"; fi 772 if [ $SRS_HTTP_CALLBACK = YES ]; then SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --with-http-callback"; else SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --without-http-callback"; fi
754 if [ $SRS_HTTP_SERVER = YES ]; then SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --with-http-server"; else SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --without-http-server"; fi 773 if [ $SRS_HTTP_SERVER = YES ]; then SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --with-http-server"; else SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --without-http-server"; fi
  774 + if [ $SRS_STREAM_CASTER = YES ]; then SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --with-stream-caster"; else SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --without-stream-caster"; fi
755 if [ $SRS_HTTP_API = YES ]; then SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --with-http-api"; else SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --without-http-api"; fi 775 if [ $SRS_HTTP_API = YES ]; then SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --with-http-api"; else SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --without-http-api"; fi
756 if [ $SRS_LIBRTMP = YES ]; then SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --with-librtmp"; else SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --without-librtmp"; fi 776 if [ $SRS_LIBRTMP = YES ]; then SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --with-librtmp"; else SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --without-librtmp"; fi
757 if [ $SRS_RESEARCH = YES ]; then SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --with-research"; else SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --without-research"; fi 777 if [ $SRS_RESEARCH = YES ]; then SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --with-research"; else SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --without-research"; fi
@@ -828,6 +848,7 @@ function check_option_conflicts() { @@ -828,6 +848,7 @@ function check_option_conflicts() {
828 if [ $SRS_FFMPEG_TOOL = RESERVED ]; then echo "you must specifies the ffmpeg, see: ./configure --help"; __check_ok=NO; fi 848 if [ $SRS_FFMPEG_TOOL = RESERVED ]; then echo "you must specifies the ffmpeg, see: ./configure --help"; __check_ok=NO; fi
829 if [ $SRS_HTTP_CALLBACK = RESERVED ]; then echo "you must specifies the http-callback, see: ./configure --help"; __check_ok=NO; fi 849 if [ $SRS_HTTP_CALLBACK = RESERVED ]; then echo "you must specifies the http-callback, see: ./configure --help"; __check_ok=NO; fi
830 if [ $SRS_HTTP_SERVER = RESERVED ]; then echo "you must specifies the http-server, see: ./configure --help"; __check_ok=NO; fi 850 if [ $SRS_HTTP_SERVER = RESERVED ]; then echo "you must specifies the http-server, see: ./configure --help"; __check_ok=NO; fi
  851 + if [ $SRS_STREAM_CASTER = RESERVED ]; then echo "you must specifies the stream-caster, see: ./configure --help"; __check_ok=NO; fi
831 if [ $SRS_HTTP_API = RESERVED ]; then echo "you must specifies the http-api, see: ./configure --help"; __check_ok=NO; fi 852 if [ $SRS_HTTP_API = RESERVED ]; then echo "you must specifies the http-api, see: ./configure --help"; __check_ok=NO; fi
832 if [ $SRS_LIBRTMP = RESERVED ]; then echo "you must specifies the librtmp, see: ./configure --help"; __check_ok=NO; fi 853 if [ $SRS_LIBRTMP = RESERVED ]; then echo "you must specifies the librtmp, see: ./configure --help"; __check_ok=NO; fi
833 if [ $SRS_RESEARCH = RESERVED ]; then echo "you must specifies the research, see: ./configure --help"; __check_ok=NO; fi 854 if [ $SRS_RESEARCH = RESERVED ]; then echo "you must specifies the research, see: ./configure --help"; __check_ok=NO; fi
@@ -142,6 +142,16 @@ stream_caster { @@ -142,6 +142,16 @@ stream_caster {
142 # whether stream caster is enabled. 142 # whether stream caster is enabled.
143 # default: off 143 # default: off
144 enabled on; 144 enabled on;
  145 + # the caster type of stream, the casters:
  146 + # mpegts_over_udp, MPEG-TS over UDP caster.
  147 + caster mpegts_over_udp;
  148 + # the output rtmp url.
  149 + # for example, rtmp://127.0.0.1/live/livestream.
  150 + output rtmp://127.0.0.1/live/livestream;
  151 + # the listen port for stream caster.
  152 + # for caster:
  153 + # mpegts_over_udp, listen at udp port.
  154 + listen 1935;
145 } 155 }
146 156
147 ############################################################################################# 157 #############################################################################################
@@ -140,6 +140,11 @@ bool SrsConfDirective::is_vhost() @@ -140,6 +140,11 @@ bool SrsConfDirective::is_vhost()
140 return name == "vhost"; 140 return name == "vhost";
141 } 141 }
142 142
  143 +bool SrsConfDirective::is_stream_caster()
  144 +{
  145 + return name == "stream_caster";
  146 +}
  147 +
143 int SrsConfDirective::parse(SrsConfigBuffer* buffer) 148 int SrsConfDirective::parse(SrsConfigBuffer* buffer)
144 { 149 {
145 return parse_conf(buffer, parse_file); 150 return parse_conf(buffer, parse_file);
@@ -519,6 +524,8 @@ int SrsConfig::reload_conf(SrsConfig* conf) @@ -519,6 +524,8 @@ int SrsConfig::reload_conf(SrsConfig* conf)
519 return ret; 524 return ret;
520 } 525 }
521 526
  527 + // TODO: FIXME: support reload stream_caster.
  528 +
522 // merge config: vhost 529 // merge config: vhost
523 if ((ret = reload_vhost(old_root)) != ERROR_SUCCESS) { 530 if ((ret = reload_vhost(old_root)) != ERROR_SUCCESS) {
524 return ret; 531 return ret;
@@ -1295,6 +1302,7 @@ int SrsConfig::check_config() @@ -1295,6 +1302,7 @@ int SrsConfig::check_config()
1295 srs_trace("srs checking config..."); 1302 srs_trace("srs checking config...");
1296 1303
1297 vector<SrsConfDirective*> vhosts = get_vhosts(); 1304 vector<SrsConfDirective*> vhosts = get_vhosts();
  1305 + vector<SrsConfDirective*> stream_casters = get_stream_casters();
1298 1306
1299 //////////////////////////////////////////////////////////////////////// 1307 ////////////////////////////////////////////////////////////////////////
1300 // check empty 1308 // check empty
@@ -1315,7 +1323,7 @@ int SrsConfig::check_config() @@ -1315,7 +1323,7 @@ int SrsConfig::check_config()
1315 && n != "srs_log_tank" && n != "srs_log_level" && n != "srs_log_file" 1323 && n != "srs_log_tank" && n != "srs_log_level" && n != "srs_log_file"
1316 && n != "max_connections" && n != "daemon" && n != "heartbeat" 1324 && n != "max_connections" && n != "daemon" && n != "heartbeat"
1317 && n != "http_api" && n != "stats" && n != "vhost" && n != "pithy_print" 1325 && n != "http_api" && n != "stats" && n != "vhost" && n != "pithy_print"
1318 - && n != "http_stream" && n != "http_server") 1326 + && n != "http_stream" && n != "http_server" && n != "stream_caster")
1319 { 1327 {
1320 ret = ERROR_SYSTEM_CONFIG_INVALID; 1328 ret = ERROR_SYSTEM_CONFIG_INVALID;
1321 srs_error("unsupported directive %s, ret=%d", n.c_str(), ret); 1329 srs_error("unsupported directive %s, ret=%d", n.c_str(), ret);
@@ -1381,6 +1389,20 @@ int SrsConfig::check_config() @@ -1381,6 +1389,20 @@ int SrsConfig::check_config()
1381 } 1389 }
1382 } 1390 }
1383 } 1391 }
  1392 + for (int n = 0; n < (int)stream_casters.size(); n++) {
  1393 + SrsConfDirective* stream_caster = stream_casters[n];
  1394 + for (int i = 0; stream_caster && i < (int)stream_caster->directives.size(); i++) {
  1395 + SrsConfDirective* conf = stream_caster->at(i);
  1396 + string n = conf->name;
  1397 + if (n != "enabled" && n != "caster" && n != "output"
  1398 + && n != "listen"
  1399 + ) {
  1400 + ret = ERROR_SYSTEM_CONFIG_INVALID;
  1401 + srs_error("unsupported stream_caster directive %s, ret=%d", n.c_str(), ret);
  1402 + return ret;
  1403 + }
  1404 + }
  1405 + }
1384 for (int n = 0; n < (int)vhosts.size(); n++) { 1406 for (int n = 0; n < (int)vhosts.size(); n++) {
1385 SrsConfDirective* vhost = vhosts[n]; 1407 SrsConfDirective* vhost = vhosts[n];
1386 for (int i = 0; vhost && i < (int)vhost->directives.size(); i++) { 1408 for (int i = 0; vhost && i < (int)vhost->directives.size(); i++) {
@@ -1969,6 +1991,77 @@ int SrsConfig::get_pithy_print_edge() @@ -1969,6 +1991,77 @@ int SrsConfig::get_pithy_print_edge()
1969 return ::atoi(pithy->arg0().c_str()); 1991 return ::atoi(pithy->arg0().c_str());
1970 } 1992 }
1971 1993
  1994 +vector<SrsConfDirective*> SrsConfig::get_stream_casters()
  1995 +{
  1996 + srs_assert(root);
  1997 +
  1998 + std::vector<SrsConfDirective*> stream_casters;
  1999 +
  2000 + for (int i = 0; i < (int)root->directives.size(); i++) {
  2001 + SrsConfDirective* conf = root->at(i);
  2002 +
  2003 + if (!conf->is_stream_caster()) {
  2004 + continue;
  2005 + }
  2006 +
  2007 + stream_casters.push_back(conf);
  2008 + }
  2009 +
  2010 + return stream_casters;
  2011 +}
  2012 +
  2013 +bool SrsConfig::get_stream_caster_enabled(SrsConfDirective* sc)
  2014 +{
  2015 + srs_assert(sc);
  2016 +
  2017 + SrsConfDirective* conf = sc->get("enabled");
  2018 + if (!conf) {
  2019 + return SRS_CONF_DEFAULT_STREAM_CASTER_ENABLED;
  2020 + }
  2021 +
  2022 + if (conf->arg0() != "on") {
  2023 + return false;
  2024 + }
  2025 +
  2026 + return true;
  2027 +}
  2028 +
  2029 +string SrsConfig::get_stream_caster_engine(SrsConfDirective* sc)
  2030 +{
  2031 + srs_assert(sc);
  2032 +
  2033 + SrsConfDirective* conf = sc->get("caster");
  2034 + if (!conf) {
  2035 + return "";
  2036 + }
  2037 +
  2038 + return conf->arg0();
  2039 +}
  2040 +
  2041 +string SrsConfig::get_stream_caster_output(SrsConfDirective* sc)
  2042 +{
  2043 + srs_assert(sc);
  2044 +
  2045 + SrsConfDirective* conf = sc->get("output");
  2046 + if (!conf) {
  2047 + return "";
  2048 + }
  2049 +
  2050 + return conf->arg0();
  2051 +}
  2052 +
  2053 +int SrsConfig::get_stream_caster_listen(SrsConfDirective* sc)
  2054 +{
  2055 + srs_assert(sc);
  2056 +
  2057 + SrsConfDirective* conf = sc->get("listen");
  2058 + if (!conf) {
  2059 + return 0;
  2060 + }
  2061 +
  2062 + return ::atoi(conf->arg0().c_str());
  2063 +}
  2064 +
1972 SrsConfDirective* SrsConfig::get_vhost(string vhost) 2065 SrsConfDirective* SrsConfig::get_vhost(string vhost)
1973 { 2066 {
1974 srs_assert(root); 2067 srs_assert(root);
@@ -80,6 +80,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -80,6 +80,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
80 80
81 #define SRS_CONF_DEFAULT_SECURITY_ENABLED false 81 #define SRS_CONF_DEFAULT_SECURITY_ENABLED false
82 82
  83 +#define SRS_CONF_DEFAULT_STREAM_CASTER_ENABLED false
  84 +#define SRS_CONF_DEFAULT_STREAM_CASTER_MPEGTS_OVER_UDP "mpegts_over_udp"
  85 +
83 #define SRS_CONF_DEFAULT_STATS_NETWORK_DEVICE_INDEX 0 86 #define SRS_CONF_DEFAULT_STATS_NETWORK_DEVICE_INDEX 0
84 87
85 #define SRS_CONF_DEFAULT_STAGE_PLAY_USER_INTERVAL_MS 10000 88 #define SRS_CONF_DEFAULT_STAGE_PLAY_USER_INTERVAL_MS 10000
@@ -188,6 +191,10 @@ public: @@ -188,6 +191,10 @@ public:
188 * whether current directive is vhost. 191 * whether current directive is vhost.
189 */ 192 */
190 virtual bool is_vhost(); 193 virtual bool is_vhost();
  194 + /**
  195 + * whether current directive is stream_caster.
  196 + */
  197 + virtual bool is_stream_caster();
191 // parse utilities 198 // parse utilities
192 public: 199 public:
193 /** 200 /**
@@ -446,6 +453,28 @@ public: @@ -446,6 +453,28 @@ public:
446 * the edge will get stream from upnode. 453 * the edge will get stream from upnode.
447 */ 454 */
448 virtual int get_pithy_print_edge(); 455 virtual int get_pithy_print_edge();
  456 +// stream_caster section
  457 +public:
  458 + /**
  459 + * get all stream_caster in config file.
  460 + */
  461 + virtual std::vector<SrsConfDirective*> get_stream_casters();
  462 + /**
  463 + * get whether the specified stream_caster is enabled.
  464 + */
  465 + virtual bool get_stream_caster_enabled(SrsConfDirective* sc);
  466 + /**
  467 + * get the engine of stream_caster, the caster config.
  468 + */
  469 + virtual std::string get_stream_caster_engine(SrsConfDirective* sc);
  470 + /**
  471 + * get the output rtmp url of stream_caster, the output config.
  472 + */
  473 + virtual std::string get_stream_caster_output(SrsConfDirective* sc);
  474 + /**
  475 + * get the listen port of stream caster.
  476 + */
  477 + virtual int get_stream_caster_listen(SrsConfDirective* sc);
449 // vhost specified section 478 // vhost specified section
450 public: 479 public:
451 /** 480 /**
@@ -93,6 +93,22 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -93,6 +93,22 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
93 // SRS_SYS_CYCLE_INTERVAL * SRS_SYS_NETWORK_DEVICE_RESOLUTION_TIMES 93 // SRS_SYS_CYCLE_INTERVAL * SRS_SYS_NETWORK_DEVICE_RESOLUTION_TIMES
94 #define SRS_SYS_NETWORK_DEVICE_RESOLUTION_TIMES 9 94 #define SRS_SYS_NETWORK_DEVICE_RESOLUTION_TIMES 9
95 95
  96 +std::string __srs_listener_type2string(SrsListenerType type)
  97 +{
  98 + switch (type) {
  99 + case SrsListenerRtmpStream:
  100 + return "RTMP";
  101 + case SrsListenerHttpApi:
  102 + return "HTTP-API";
  103 + case SrsListenerHttpStream:
  104 + return "HTTP-Server";
  105 + case SrsListenerMpegTsOverUdp:
  106 + return "MPEG-TS over UDP";
  107 + default:
  108 + return "UNKONWN";
  109 + }
  110 +}
  111 +
96 SrsListener::SrsListener(SrsServer* server, SrsListenerType type) 112 SrsListener::SrsListener(SrsServer* server, SrsListenerType type)
97 { 113 {
98 fd = -1; 114 fd = -1;
@@ -174,18 +190,15 @@ int SrsListener::listen(int port) @@ -174,18 +190,15 @@ int SrsListener::listen(int port)
174 } 190 }
175 srs_verbose("create st listen thread success, port=%d", port); 191 srs_verbose("create st listen thread success, port=%d", port);
176 192
177 - srs_trace("listen thread cid=%d, current_cid=%d, " 193 + srs_info("listen thread cid=%d, current_cid=%d, "
178 "listen at port=%d, type=%d, fd=%d started success, port=%d", 194 "listen at port=%d, type=%d, fd=%d started success, port=%d",
179 pthread->cid(), _srs_context->get_id(), _port, _type, fd, port); 195 pthread->cid(), _srs_context->get_id(), _port, _type, fd, port);
  196 +
  197 + srs_trace("%s listen at tcp://%d, fd=%d", __srs_listener_type2string(_type).c_str(), _port, fd);
180 198
181 return ret; 199 return ret;
182 } 200 }
183 201
184 -void SrsListener::on_thread_start()  
185 -{  
186 - srs_trace("listen cycle start, port=%d, type=%d, fd=%d", _port, _type, fd);  
187 -}  
188 -  
189 int SrsListener::cycle() 202 int SrsListener::cycle()
190 { 203 {
191 int ret = ERROR_SUCCESS; 204 int ret = ERROR_SUCCESS;
@@ -207,6 +220,86 @@ int SrsListener::cycle() @@ -207,6 +220,86 @@ int SrsListener::cycle()
207 return ret; 220 return ret;
208 } 221 }
209 222
  223 +SrsUdpListener::SrsUdpListener(SrsServer* server, SrsListenerType type) : SrsListener(server, type)
  224 +{
  225 +}
  226 +
  227 +SrsUdpListener::~SrsUdpListener()
  228 +{
  229 +}
  230 +
  231 +int SrsUdpListener::listen(int port)
  232 +{
  233 + int ret = ERROR_SUCCESS;
  234 +
  235 + // the caller already ensure the type is ok,
  236 + // we just assert here for unknown stream caster.
  237 + srs_assert(_type == SrsListenerMpegTsOverUdp);
  238 +
  239 + _port = port;
  240 +
  241 + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
  242 + ret = ERROR_SOCKET_CREATE;
  243 + srs_error("create linux socket error. port=%d, ret=%d", port, ret);
  244 + return ret;
  245 + }
  246 + srs_verbose("create linux socket success. port=%d, fd=%d", port, fd);
  247 +
  248 + int reuse_socket = 1;
  249 + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_socket, sizeof(int)) == -1) {
  250 + ret = ERROR_SOCKET_SETREUSE;
  251 + srs_error("setsockopt reuse-addr error. port=%d, ret=%d", port, ret);
  252 + return ret;
  253 + }
  254 + srs_verbose("setsockopt reuse-addr success. port=%d, fd=%d", port, fd);
  255 +
  256 + sockaddr_in addr;
  257 + addr.sin_family = AF_INET;
  258 + addr.sin_port = htons(_port);
  259 + addr.sin_addr.s_addr = INADDR_ANY;
  260 + if (bind(fd, (const sockaddr*)&addr, sizeof(sockaddr_in)) == -1) {
  261 + ret = ERROR_SOCKET_BIND;
  262 + srs_error("bind socket error. port=%d, ret=%d", port, ret);
  263 + return ret;
  264 + }
  265 + srs_verbose("bind socket success. port=%d, fd=%d", port, fd);
  266 +
  267 + if ((stfd = st_netfd_open_socket(fd)) == NULL){
  268 + ret = ERROR_ST_OPEN_SOCKET;
  269 + srs_error("st_netfd_open_socket open socket failed. port=%d, ret=%d", port, ret);
  270 + return ret;
  271 + }
  272 + srs_verbose("st open socket success. port=%d, fd=%d", port, fd);
  273 +
  274 + if ((ret = pthread->start()) != ERROR_SUCCESS) {
  275 + srs_error("st_thread_create listen thread error. port=%d, ret=%d", port, ret);
  276 + return ret;
  277 + }
  278 + srs_verbose("create st listen thread success, port=%d", port);
  279 +
  280 + srs_info("listen thread cid=%d, current_cid=%d, "
  281 + "listen at port=%d, type=%d, fd=%d started success, port=%d",
  282 + pthread->cid(), _srs_context->get_id(), _port, _type, fd, port);
  283 +
  284 + srs_trace("%s listen at udp://%d, fd=%d", __srs_listener_type2string(_type).c_str(), _port, fd);
  285 +
  286 + return ret;
  287 +}
  288 +
  289 +int SrsUdpListener::cycle()
  290 +{
  291 + int ret = ERROR_SUCCESS;
  292 +
  293 + // the caller already ensure the type is ok,
  294 + // we just assert here for unknown stream caster.
  295 + srs_assert(_type == SrsListenerMpegTsOverUdp);
  296 +
  297 + // TODO: FIXME: recv udp packet.
  298 + st_sleep(1);
  299 +
  300 + return ret;
  301 +}
  302 +
210 SrsSignalManager* SrsSignalManager::instance = NULL; 303 SrsSignalManager* SrsSignalManager::instance = NULL;
211 304
212 SrsSignalManager::SrsSignalManager(SrsServer* server) 305 SrsSignalManager::SrsSignalManager(SrsServer* server)
@@ -608,6 +701,10 @@ int SrsServer::listen() @@ -608,6 +701,10 @@ int SrsServer::listen()
608 return ret; 701 return ret;
609 } 702 }
610 703
  704 + if ((ret = listen_stream_caster()) != ERROR_SUCCESS) {
  705 + return ret;
  706 + }
  707 +
611 return ret; 708 return ret;
612 } 709 }
613 710
@@ -869,6 +966,53 @@ int SrsServer::listen_http_stream() @@ -869,6 +966,53 @@ int SrsServer::listen_http_stream()
869 return ret; 966 return ret;
870 } 967 }
871 968
  969 +int SrsServer::listen_stream_caster()
  970 +{
  971 + int ret = ERROR_SUCCESS;
  972 +
  973 +#ifdef SRS_AUTO_STREAM_CASTER
  974 + close_listeners(SrsListenerMpegTsOverUdp);
  975 +
  976 + std::vector<SrsConfDirective*>::iterator it;
  977 + std::vector<SrsConfDirective*> stream_casters = _srs_config->get_stream_casters();
  978 +
  979 + for (it = stream_casters.begin(); it != stream_casters.end(); ++it) {
  980 + SrsConfDirective* stream_caster = *it;
  981 + if (!_srs_config->get_stream_caster_enabled(stream_caster)) {
  982 + continue;
  983 + }
  984 +
  985 + SrsUdpListener* listener = NULL;
  986 +
  987 + std::string caster = _srs_config->get_stream_caster_engine(stream_caster);
  988 + if (caster == SRS_CONF_DEFAULT_STREAM_CASTER_MPEGTS_OVER_UDP) {
  989 + listener = new SrsUdpListener(this, SrsListenerMpegTsOverUdp);
  990 + } else {
  991 + ret = ERROR_STREAM_CASTER_ENGINE;
  992 + srs_error("unsupported stream caster %s. ret=%d", caster.c_str(), ret);
  993 + return ret;
  994 + }
  995 + srs_assert(listener != NULL);
  996 +
  997 + listeners.push_back(listener);
  998 +
  999 + int port = _srs_config->get_stream_caster_listen(stream_caster);
  1000 + if (port <= 0) {
  1001 + ret = ERROR_STREAM_CASTER_PORT;
  1002 + srs_error("invalid stream caster port %d. ret=%d", port, ret);
  1003 + return ret;
  1004 + }
  1005 +
  1006 + if ((ret = listener->listen(port)) != ERROR_SUCCESS) {
  1007 + srs_error("StreamCaster listen at port %d failed. ret=%d", port, ret);
  1008 + return ret;
  1009 + }
  1010 + }
  1011 +#endif
  1012 +
  1013 + return ret;
  1014 +}
  1015 +
872 void SrsServer::close_listeners(SrsListenerType type) 1016 void SrsServer::close_listeners(SrsListenerType type)
873 { 1017 {
874 std::vector<SrsListener*>::iterator it; 1018 std::vector<SrsListener*>::iterator it;
@@ -50,18 +50,23 @@ class SrsKbps; @@ -50,18 +50,23 @@ class SrsKbps;
50 enum SrsListenerType 50 enum SrsListenerType
51 { 51 {
52 // RTMP client, 52 // RTMP client,
53 - SrsListenerRtmpStream = 0, 53 + SrsListenerRtmpStream = 0,
54 // HTTP api, 54 // HTTP api,
55 - SrsListenerHttpApi = 1, 55 + SrsListenerHttpApi = 1,
56 // HTTP stream, HDS/HLS/DASH 56 // HTTP stream, HDS/HLS/DASH
57 - SrsListenerHttpStream = 2 57 + SrsListenerHttpStream = 2,
  58 + // UDP stream, MPEG-TS over udp.
  59 + SrsListenerMpegTsOverUdp = 3,
58 }; 60 };
59 61
  62 +/**
  63 +* the common tcp listener, for RTMP/HTTP server.
  64 +*/
60 class SrsListener : public ISrsThreadHandler 65 class SrsListener : public ISrsThreadHandler
61 { 66 {
62 public: 67 public:
63 SrsListenerType _type; 68 SrsListenerType _type;
64 -private: 69 +protected:
65 int fd; 70 int fd;
66 st_netfd_t stfd; 71 st_netfd_t stfd;
67 int _port; 72 int _port;
@@ -75,7 +80,21 @@ public: @@ -75,7 +80,21 @@ public:
75 virtual int listen(int port); 80 virtual int listen(int port);
76 // interface ISrsThreadHandler. 81 // interface ISrsThreadHandler.
77 public: 82 public:
78 - virtual void on_thread_start(); 83 + virtual int cycle();
  84 +};
  85 +
  86 +/**
  87 +* the udp listener, for udp server.
  88 +*/
  89 +class SrsUdpListener : public SrsListener
  90 +{
  91 +public:
  92 + SrsUdpListener(SrsServer* server, SrsListenerType type);
  93 + virtual ~SrsUdpListener();
  94 +public:
  95 + virtual int listen(int port);
  96 +// interface ISrsThreadHandler.
  97 +public:
79 virtual int cycle(); 98 virtual int cycle();
80 }; 99 };
81 100
@@ -211,6 +230,7 @@ private: @@ -211,6 +230,7 @@ private:
211 virtual int listen_rtmp(); 230 virtual int listen_rtmp();
212 virtual int listen_http_api(); 231 virtual int listen_http_api();
213 virtual int listen_http_stream(); 232 virtual int listen_http_stream();
  233 + virtual int listen_stream_caster();
214 /** 234 /**
215 * close the listeners for specified type, 235 * close the listeners for specified type,
216 * remove the listen object from manager. 236 * remove the listen object from manager.
@@ -204,7 +204,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -204,7 +204,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
204 #define ERROR_AAC_DATA_INVALID 3048 204 #define ERROR_AAC_DATA_INVALID 3048
205 205
206 /////////////////////////////////////////////////////// 206 ///////////////////////////////////////////////////////
207 -// HTTP protocol error. 207 +// HTTP/StreamCaster protocol error.
208 /////////////////////////////////////////////////////// 208 ///////////////////////////////////////////////////////
209 #define ERROR_HTTP_PATTERN_EMPTY 4000 209 #define ERROR_HTTP_PATTERN_EMPTY 4000
210 #define ERROR_HTTP_PATTERN_DUPLICATED 4001 210 #define ERROR_HTTP_PATTERN_DUPLICATED 4001
@@ -216,6 +216,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -216,6 +216,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
216 #define ERROR_AAC_DECODE_ERROR 4007 216 #define ERROR_AAC_DECODE_ERROR 4007
217 #define ERROR_KERNEL_MP3_STREAM_CLOSED 4008 217 #define ERROR_KERNEL_MP3_STREAM_CLOSED 4008
218 #define ERROR_MP3_DECODE_ERROR 4009 218 #define ERROR_MP3_DECODE_ERROR 4009
  219 +#define ERROR_STREAM_CASTER_ENGINE 4010
  220 +#define ERROR_STREAM_CASTER_PORT 4011
219 221
220 /** 222 /**
221 * whether the error code is an system control error. 223 * whether the error code is an system control error.