winlin

support HLS, refine the dir use app

@@ -13,6 +13,8 @@ vhost __defaultVhost__ { @@ -13,6 +13,8 @@ vhost __defaultVhost__ {
13 gop_cache on; 13 gop_cache on;
14 hls on; 14 hls on;
15 hls_path ./objs/nginx/html; 15 hls_path ./objs/nginx/html;
  16 + hls_fragment 10;
  17 + hls_window 60;
16 } 18 }
17 # the vhost disabled. 19 # the vhost disabled.
18 vhost removed.vhost.com { 20 vhost removed.vhost.com {
@@ -39,6 +41,12 @@ vhost no-hls.vhost.com { @@ -39,6 +41,12 @@ vhost no-hls.vhost.com {
39 # in a word, the hls_path is for vhost. 41 # in a word, the hls_path is for vhost.
40 # default: ./objs/nginx/html 42 # default: ./objs/nginx/html
41 hls_path /data/nginx/html; 43 hls_path /data/nginx/html;
  44 + # the hls fragment in seconds, the duration of a piece of ts.
  45 + # default: 10
  46 + hls_fragment 10;
  47 + # the hls window in seconds, the number of ts in m3u8.
  48 + # default: 60
  49 + hls_window 60;
42 } 50 }
43 # the vhost with hls disabled. 51 # the vhost with hls disabled.
44 vhost no-hls.vhost.com { 52 vhost no-hls.vhost.com {
@@ -332,7 +332,7 @@ int SrsClient::publish(SrsSource* source, bool is_fmle) @@ -332,7 +332,7 @@ int SrsClient::publish(SrsSource* source, bool is_fmle)
332 SrsPithyPrint pithy_print(SRS_STAGE_PUBLISH_USER); 332 SrsPithyPrint pithy_print(SRS_STAGE_PUBLISH_USER);
333 333
334 // notify the hls to prepare when publish start. 334 // notify the hls to prepare when publish start.
335 - if ((ret = source->on_publish(req->vhost, req->stream)) != ERROR_SUCCESS) { 335 + if ((ret = source->on_publish(req->vhost, req->app, req->stream)) != ERROR_SUCCESS) {
336 srs_error("hls on_publish failed. ret=%d", ret); 336 srs_error("hls on_publish failed. ret=%d", ret);
337 return ret; 337 return ret;
338 } 338 }
@@ -109,7 +109,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -109,7 +109,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
109 109
110 #define ERROR_HLS_METADATA 600 110 #define ERROR_HLS_METADATA 600
111 #define ERROR_HLS_DECODE_ERROR 601 111 #define ERROR_HLS_DECODE_ERROR 601
112 -//#define ERROR_HLS_BUSY 602 112 +#define ERROR_HLS_CREATE_DIR 602
113 #define ERROR_HLS_OPEN_FAILED 603 113 #define ERROR_HLS_OPEN_FAILED 603
114 #define ERROR_HLS_WRITE_FAILED 604 114 #define ERROR_HLS_WRITE_FAILED 604
115 #define ERROR_HLS_AAC_FRAME_LENGTH 605 115 #define ERROR_HLS_AAC_FRAME_LENGTH 605
@@ -403,12 +403,13 @@ SrsHLS::~SrsHLS() @@ -403,12 +403,13 @@ SrsHLS::~SrsHLS()
403 srs_freep(video_frame); 403 srs_freep(video_frame);
404 } 404 }
405 405
406 -int SrsHLS::on_publish(std::string _vhost, std::string _stream) 406 +int SrsHLS::on_publish(std::string _vhost, std::string _app, std::string _stream)
407 { 407 {
408 int ret = ERROR_SUCCESS; 408 int ret = ERROR_SUCCESS;
409 409
410 vhost = _vhost; 410 vhost = _vhost;
411 stream = _stream; 411 stream = _stream;
  412 + app = _app;
412 413
413 if ((ret = reopen()) != ERROR_SUCCESS) { 414 if ((ret = reopen()) != ERROR_SUCCESS) {
414 return ret; 415 return ret;
@@ -555,6 +556,7 @@ int SrsHLS::on_video(SrsSharedPtrMessage* video) @@ -555,6 +556,7 @@ int SrsHLS::on_video(SrsSharedPtrMessage* video)
555 if (sample->frame_type == SrsCodecVideoAVCFrameKeyFrame) { 556 if (sample->frame_type == SrsCodecVideoAVCFrameKeyFrame) {
556 int64_t diff = stream_dts - m3u8_dts; 557 int64_t diff = stream_dts - m3u8_dts;
557 // 10s. 558 // 10s.
  559 + // TODO: config it.
558 if (diff / 90000 >= 10) { 560 if (diff / 90000 >= 10) {
559 if ((ret = reopen()) != ERROR_SUCCESS) { 561 if ((ret = reopen()) != ERROR_SUCCESS) {
560 return ret; 562 return ret;
@@ -590,6 +592,11 @@ int SrsHLS::reopen() @@ -590,6 +592,11 @@ int SrsHLS::reopen()
590 hls_path = conf->arg0(); 592 hls_path = conf->arg0();
591 } 593 }
592 594
  595 + // create dir for app.
  596 + if ((ret = create_dir()) != ERROR_SUCCESS) {
  597 + return ret;
  598 + }
  599 +
593 // start new segment. 600 // start new segment.
594 if (current) { 601 if (current) {
595 current->duration = (stream_dts - current->segment_start_dts) / 90000.0; 602 current->duration = (stream_dts - current->segment_start_dts) / 90000.0;
@@ -610,6 +617,8 @@ int SrsHLS::reopen() @@ -610,6 +617,8 @@ int SrsHLS::reopen()
610 617
611 current->full_path = hls_path; 618 current->full_path = hls_path;
612 current->full_path += "/"; 619 current->full_path += "/";
  620 + current->full_path += app;
  621 + current->full_path += "/";
613 current->full_path += filename; 622 current->full_path += filename;
614 623
615 // TODO: support base url, and so on. 624 // TODO: support base url, and so on.
@@ -619,7 +628,7 @@ int SrsHLS::reopen() @@ -619,7 +628,7 @@ int SrsHLS::reopen()
619 srs_error("open hls muxer failed. ret=%d", ret); 628 srs_error("open hls muxer failed. ret=%d", ret);
620 return ret; 629 return ret;
621 } 630 }
622 - srs_trace("open HLS muxer success. vhost=%s, path=%s", vhost.c_str(), current->full_path.c_str()); 631 + srs_info("open HLS muxer success. vhost=%s, path=%s", vhost.c_str(), current->full_path.c_str());
623 632
624 return ret; 633 return ret;
625 } 634 }
@@ -628,16 +637,33 @@ int SrsHLS::refresh_m3u8() @@ -628,16 +637,33 @@ int SrsHLS::refresh_m3u8()
628 { 637 {
629 int ret = ERROR_SUCCESS; 638 int ret = ERROR_SUCCESS;
630 639
  640 + std::string m3u8_file = hls_path;
  641 + m3u8_file += "/";
  642 + m3u8_file += app;
  643 + m3u8_file += "/";
  644 + m3u8_file += stream;
  645 + m3u8_file += ".m3u8";
  646 +
  647 + m3u8 = m3u8_file;
  648 + m3u8_file += ".temp";
  649 +
631 int fd = -1; 650 int fd = -1;
632 - ret = _refresh_m3u8(fd); 651 + ret = _refresh_m3u8(fd, m3u8_file);
633 if (fd >= 0) { 652 if (fd >= 0) {
634 close(fd); 653 close(fd);
  654 + if (rename(m3u8_file.c_str(), m3u8.c_str()) < 0) {
  655 + ret = ERROR_HLS_WRITE_FAILED;
  656 + srs_error("rename m3u8 file failed. ret=%d", ret);
  657 + }
635 } 658 }
636 659
  660 + // remove the temp file.
  661 + unlink(m3u8_file.c_str());
  662 +
637 return ret; 663 return ret;
638 } 664 }
639 665
640 -int SrsHLS::_refresh_m3u8(int& fd) 666 +int SrsHLS::_refresh_m3u8(int& fd, std::string m3u8_file)
641 { 667 {
642 int ret = ERROR_SUCCESS; 668 int ret = ERROR_SUCCESS;
643 669
@@ -646,19 +672,14 @@ int SrsHLS::_refresh_m3u8(int& fd) @@ -646,19 +672,14 @@ int SrsHLS::_refresh_m3u8(int& fd)
646 return ret; 672 return ret;
647 } 673 }
648 674
649 - m3u8 = hls_path;  
650 - m3u8 += "/";  
651 - m3u8 += stream;  
652 - m3u8 += ".m3u8";  
653 -  
654 int flags = O_CREAT|O_WRONLY|O_TRUNC; 675 int flags = O_CREAT|O_WRONLY|O_TRUNC;
655 mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH; 676 mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH;
656 - if ((fd = ::open(m3u8.c_str(), flags, mode)) < 0) { 677 + if ((fd = ::open(m3u8_file.c_str(), flags, mode)) < 0) {
657 ret = ERROR_HLS_OPEN_FAILED; 678 ret = ERROR_HLS_OPEN_FAILED;
658 - srs_error("open m3u8 file %s failed. ret=%d", m3u8.c_str(), ret); 679 + srs_error("open m3u8 file %s failed. ret=%d", m3u8_file.c_str(), ret);
659 return ret; 680 return ret;
660 } 681 }
661 - srs_info("open m3u8 file %s success.", m3u8.c_str()); 682 + srs_info("open m3u8 file %s success.", m3u8_file.c_str());
662 683
663 // #EXTM3U\n#EXT-X-VERSION:3\n 684 // #EXTM3U\n#EXT-X-VERSION:3\n
664 char header[] = { 685 char header[] = {
@@ -728,8 +749,31 @@ int SrsHLS::_refresh_m3u8(int& fd) @@ -728,8 +749,31 @@ int SrsHLS::_refresh_m3u8(int& fd)
728 } 749 }
729 srs_verbose("write m3u8 segment uri success."); 750 srs_verbose("write m3u8 segment uri success.");
730 } 751 }
731 - srs_info("write m3u8 %s success.", m3u8.c_str()); 752 + srs_info("write m3u8 %s success.", m3u8_file.c_str());
  753 +
  754 + return ret;
  755 +}
  756 +
  757 +int SrsHLS::create_dir()
  758 +{
  759 + int ret = ERROR_SUCCESS;
  760 +
  761 + std::string app_dir = hls_path;
  762 + app_dir += "/";
  763 + app_dir += app;
732 764
  765 + // TODO: cleanup the dir when startup.
  766 +
  767 + mode_t mode = S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IXOTH;
  768 + if (::mkdir(app_dir.c_str(), mode) < 0) {
  769 + if (errno != EEXIST) {
  770 + ret = ERROR_HLS_CREATE_DIR;
  771 + srs_error("create app dir %s failed. ret=%d", app_dir.c_str(), ret);
  772 + return ret;
  773 + }
  774 + }
  775 + srs_info("create app dir %s success.", app_dir.c_str());
  776 +
733 return ret; 777 return ret;
734 } 778 }
735 779
@@ -72,6 +72,7 @@ class SrsHLS @@ -72,6 +72,7 @@ class SrsHLS
72 private: 72 private:
73 std::string vhost; 73 std::string vhost;
74 std::string stream; 74 std::string stream;
  75 + std::string app;
75 std::string hls_path; 76 std::string hls_path;
76 private: 77 private:
77 int file_index; 78 int file_index;
@@ -103,7 +104,7 @@ public: @@ -103,7 +104,7 @@ public:
103 SrsHLS(); 104 SrsHLS();
104 virtual ~SrsHLS(); 105 virtual ~SrsHLS();
105 public: 106 public:
106 - virtual int on_publish(std::string _vhost, std::string _stream); 107 + virtual int on_publish(std::string _vhost, std::string _app, std::string _stream);
107 virtual void on_unpublish(); 108 virtual void on_unpublish();
108 virtual int on_meta_data(SrsOnMetaDataPacket* metadata); 109 virtual int on_meta_data(SrsOnMetaDataPacket* metadata);
109 virtual int on_audio(SrsSharedPtrMessage* audio); 110 virtual int on_audio(SrsSharedPtrMessage* audio);
@@ -111,7 +112,8 @@ public: @@ -111,7 +112,8 @@ public:
111 private: 112 private:
112 virtual int reopen(); 113 virtual int reopen();
113 virtual int refresh_m3u8(); 114 virtual int refresh_m3u8();
114 - virtual int _refresh_m3u8(int& fd); 115 + virtual int _refresh_m3u8(int& fd, std::string m3u8_file);
  116 + virtual int create_dir();
115 }; 117 };
116 118
117 class SrsTSMuxer 119 class SrsTSMuxer
@@ -452,9 +452,9 @@ int SrsSource::on_video(SrsCommonMessage* video) @@ -452,9 +452,9 @@ int SrsSource::on_video(SrsCommonMessage* video)
452 return ret; 452 return ret;
453 } 453 }
454 454
455 -int SrsSource::on_publish(std::string vhost, std::string stream) 455 +int SrsSource::on_publish(std::string vhost, std::string app, std::string stream)
456 { 456 {
457 - return hls->on_publish(vhost, stream); 457 + return hls->on_publish(vhost, app, stream);
458 } 458 }
459 459
460 void SrsSource::on_unpublish() 460 void SrsSource::on_unpublish()
@@ -166,7 +166,7 @@ public: @@ -166,7 +166,7 @@ public:
166 virtual int on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata); 166 virtual int on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata);
167 virtual int on_audio(SrsCommonMessage* audio); 167 virtual int on_audio(SrsCommonMessage* audio);
168 virtual int on_video(SrsCommonMessage* video); 168 virtual int on_video(SrsCommonMessage* video);
169 - virtual int on_publish(std::string vhost, std::string stream); 169 + virtual int on_publish(std::string vhost, std::string app, std::string stream);
170 virtual void on_unpublish(); 170 virtual void on_unpublish();
171 public: 171 public:
172 virtual int create_consumer(SrsConsumer*& consumer); 172 virtual int create_consumer(SrsConsumer*& consumer);