From 38b0b1dab28e3b232c62dbb5e5f5552c2af22aae Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 25 Aug 2021 08:11:44 +0800 Subject: [PATCH 1/3] Squash: Fix ingest bug. Refine AUTHORS. --- .github/ISSUE_TEMPLATE | 4 ++ README.md | 17 ++++---- trunk/AUTHORS.md | 66 ++++++++++++++++-------------- trunk/scripts/new_authors.sh | 2 +- trunk/src/app/srs_app_config.cpp | 4 +- trunk/src/app/srs_app_process.cpp | 45 ++++++++++++-------- trunk/src/app/srs_app_process.hpp | 3 ++ trunk/src/main/srs_main_server.cpp | 3 +- 8 files changed, 84 insertions(+), 60 deletions(-) diff --git a/.github/ISSUE_TEMPLATE b/.github/ISSUE_TEMPLATE index fa6f266ec..96836bbd7 100644 --- a/.github/ISSUE_TEMPLATE +++ b/.github/ISSUE_TEMPLATE @@ -7,6 +7,10 @@ assignees: '' --- +> 注意:不提供以下信息的Issue会被直接删除(Please follow issue template, or we will delete it) + +> 注意:咨询和讨论请提交到SRS星球(Please ask question at) http://bbs.ossrs.net + **描述(Description)** > 描述你遇到了什么问题(Please description your issue here) diff --git a/README.md b/README.md index 829a61197..01fd64992 100755 --- a/README.md +++ b/README.md @@ -74,14 +74,15 @@ Other important wiki: The [TOC(Technical Oversight Committee)](trunk/AUTHORS.md#toc) and [contributors](trunk/AUTHORS.md#contributors): -* [Winlin](https://github.com/winlinvip): All areas of streaming server and documents. -* [Wenjie](https://github.com/wenjiegit): The focus of his work is on the [HDS](https://github.com/simple-rtmp-server/srs/wiki/v4_CN_DeliveryHDS) module. -* [Runner365](https://github.com/runner365): The focus of his work is on the [SRT](https://github.com/simple-rtmp-server/srs/wiki/v4_CN_SRTWiki) module. -* [John](https://github.com/xiaozhihong): Focus on [WebRTC](https://github.com/simple-rtmp-server/srs/wiki/v4_CN_WebRTC) module. -* [B.P.Y(Bepartofyou)](https://github.com/Bepartofyou): Focus on [WebRTC](https://github.com/simple-rtmp-server/srs/wiki/v4_CN_WebRTC) module. -* [Lixin](https://github.com/xialixin): Focus on [GB28181](https://github.com/ossrs/srs/issues/1500) module. -* [Mozhan](https://github.com/lipeng19811218): Focus on [WebRTC](https://github.com/simple-rtmp-server/srs/wiki/v4_CN_WebRTC) module. -* [Jinxue](https://github.com/chen-guanghua): Focus on [WebRTC](https://github.com/simple-rtmp-server/srs/wiki/v4_CN_WebRTC) module. +* [Winlin](https://github.com/winlinvip): Focus on [issues/PR](https://github.com/ossrs/srs/issues) and tests now. +* [ZhaoWenjie](https://github.com/wenjiegit): Focus on [HDS](https://github.com/simple-rtmp-server/srs/wiki/v4_CN_DeliveryHDS) module. +* [ShiWei](https://github.com/runner365): Focus on [SRT](https://github.com/simple-rtmp-server/srs/wiki/v4_CN_SRTWiki) module. +* [XiaoZhihong](https://github.com/xiaozhihong): Focus on [WebRTC](https://github.com/simple-rtmp-server/srs/wiki/v4_CN_WebRTC) module. +* [WuPengqiang](https://github.com/Bepartofyou): Focus on [WebRTC](https://github.com/simple-rtmp-server/srs/wiki/v4_CN_WebRTC) module. +* [XiaLixin](https://github.com/xialixin): Focus on [GB28181](https://github.com/ossrs/srs/issues/1500) module. +* [LiPeng](https://github.com/lipeng19811218): Focus on [WebRTC](https://github.com/simple-rtmp-server/srs/wiki/v4_CN_WebRTC) module. +* [ChenGuanghua](https://github.com/chen-guanghua): Focus on [WebRTC](https://github.com/simple-rtmp-server/srs/wiki/v4_CN_WebRTC) module. +* [ChenHaibo](https://github.com/duiniuluantanqin): Focus on [GB28181](https://github.com/ossrs/srs/issues/1500) and [API](https://github.com/ossrs/srs/issues/1657) module. A big `THANK YOU` also goes to: diff --git a/trunk/AUTHORS.md b/trunk/AUTHORS.md index c07346704..8a0b32e6e 100644 --- a/trunk/AUTHORS.md +++ b/trunk/AUTHORS.md @@ -2,25 +2,26 @@ The TOC(Technical Oversight Committee): -- `winlinvip` -- `wenjiegit` -- `xialixin` -- `runner365` -- `xiaozhihong` -- `Bepartofyou` -- `chen-guanghua` -- `lipeng19811218` +- `Winlin` +- `ZhaoWenjie` +- `ShiWei` +- `XiaoZhihong` +- `WuPengqiang` +- `XiaLixin` +- `LiPeng` +- `ChenGuanghua` +- `ChenHaibo` ## CONTRIBUTORS CONTRIBUTORS ordered by first contribution. -* `winlinvip` -* `winlinvip` -* `winlinvip` -* `wenjiegit` -* `wenjiegit<740936897@qq.com>` -* `wenjiegit` +* `Winlin` +* `Winlin` +* `Winlin` +* `ZhaoWenjie` +* `ZhaoWenjie<740936897@qq.com>` +* `ZhaoWenjie` * `xiangcheng.liu` * `naijia.liu` * `alcoholyi` @@ -69,33 +70,34 @@ CONTRIBUTORS ordered by first contribution. * `qiang.li` * `HungMingWu` * `Himer` -* `xialixin` -* `xialixin<68469352@qq.com>` -* `xialixin` -* `xialixin` +* `XiaLixin` +* `XiaLixin<68469352@qq.com>` +* `XiaLixin` +* `XiaLixin` * `alphonsetai` * `Michael.Ma` * `lam2003` -* `runner365` -* `runner365` +* `ShiWei` +* `ShiWei` * `XiaofengWang` -* `xiaozhihong` -* `xiaozhihong` -* `xiaozhihong` +* `XiaoZhihong` +* `XiaoZhihong` +* `XiaoZhihong` * `yanghuiwen` -* `Bepartofyou<309554135@qq.com>` -* `Bepartofyou` +* `WuPengqiang<309554135@qq.com>` +* `WuPengqiang` * `l<22312935+lam2003@users.noreply.github.com>` * `xfalcon` -* `chen-guanghua` -* `chen-guanghua` -* `lipeng19811218` -* `lipeng19811218` +* `ChenGuanghua` +* `ChenGuanghua` +* `LiPeng` +* `LiPeng` * `yajun18` * `liulichuan` * `yapingcat` * `chenchengbin` -* `duiniuluantanqin` +* `ChenHaibo<495810242@qq.com>` +* `ChenHaibo` * `jasongwq` * `yinjiaoyuan` * `PieerePi` @@ -107,4 +109,6 @@ CONTRIBUTORS ordered by first contribution. * `stone` * `cfw11<34058899+cfw11@users.noreply.github.com>` * `Hung-YiChen` -* `long` \ No newline at end of file +* `long` +* `matthew1838<77285055+matthew1838@users.noreply.github.com>` +* `rise` \ No newline at end of file diff --git a/trunk/scripts/new_authors.sh b/trunk/scripts/new_authors.sh index 3a4bc0b83..cd12846a5 100755 --- a/trunk/scripts/new_authors.sh +++ b/trunk/scripts/new_authors.sh @@ -12,5 +12,5 @@ for author in $authors; do username=$(echo $author |awk -F '@' '{print $1}') grep $username $AFILE 1>/dev/null 2>/dev/null && continue; - git log -1 --author="$author" --format='%an<%ae>'| sed 's/ //g' + echo "* $(git log -1 --author="$author" --format='`%an<%ae>`'| sed 's/ //g')" done diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 147dd1ed8..7469ac569 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -3526,7 +3526,7 @@ srs_error_t SrsConfig::parse_argv(int& i, char** argv) void SrsConfig::print_help(char** argv) { printf( - "%s, %s, %s, created by %s\n\n" + "%s, %s, %s, created by %sand %s\n\n" "Usage: %s <-h?vVgG>|<[-t] -c filename>\n" "Options:\n" " -?, -h : Show this help and exit 0.\n" @@ -3539,7 +3539,7 @@ void SrsConfig::print_help(char** argv) " %s -t -c %s\n" " %s -c %s\n", RTMP_SIG_SRS_SERVER, RTMP_SIG_SRS_URL, RTMP_SIG_SRS_LICENSE, - RTMP_SIG_SRS_AUTHORS, + RTMP_SIG_SRS_AUTHORS, SRS_CONSTRIBUTORS, argv[0], argv[0], argv[0], SRS_CONF_DEFAULT_COFNIG_FILE, argv[0], SRS_CONF_DEFAULT_COFNIG_FILE); } diff --git a/trunk/src/app/srs_app_process.cpp b/trunk/src/app/srs_app_process.cpp index cea83ff41..cfc2f8138 100644 --- a/trunk/src/app/srs_app_process.cpp +++ b/trunk/src/app/srs_app_process.cpp @@ -153,6 +153,30 @@ srs_error_t srs_redirect_output(string from_file, int to_fd) return err; } +srs_error_t SrsProcess::redirect_io() +{ + srs_error_t err = srs_success; + + // for the stdout, ignore when not specified. + // redirect stdout to file if possible. + if ((err = srs_redirect_output(stdout_file, STDOUT_FILENO)) != srs_success) { + return srs_error_wrap(err, "redirect stdout"); + } + + // for the stderr, ignore when not specified. + // redirect stderr to file if possible. + if ((err = srs_redirect_output(stderr_file, STDERR_FILENO)) != srs_success) { + return srs_error_wrap(err, "redirect stderr"); + } + + // No stdin for process, @bug https://github.com/ossrs/srs/issues/1592 + if ((err = srs_redirect_output("/dev/null", STDIN_FILENO)) != srs_success) { + return srs_error_wrap(err, "redirect /dev/null"); + } + + return err; +} + srs_error_t SrsProcess::start() { srs_error_t err = srs_success; @@ -182,24 +206,13 @@ srs_error_t SrsProcess::start() // ignore the SIGINT and SIGTERM signal(SIGINT, SIG_IGN); signal(SIGTERM, SIG_IGN); - - // for the stdout, ignore when not specified. - // redirect stdout to file if possible. - if ((err = srs_redirect_output(stdout_file, STDOUT_FILENO)) != srs_success) { - return srs_error_wrap(err, "redirect output"); + + // redirect standard I/O, if it failed, output error to stdout, and exit child process. + if ((err = redirect_io()) != srs_success) { + fprintf(stdout, "child process error, %s\n", srs_error_desc(err).c_str()); + exit(-1); } - // for the stderr, ignore when not specified. - // redirect stderr to file if possible. - if ((err = srs_redirect_output(stderr_file, STDERR_FILENO)) != srs_success) { - return srs_error_wrap(err, "redirect output"); - } - - // No stdin for process, @bug https://github.com/ossrs/srs/issues/1592 - if ((err = srs_redirect_output("/dev/null", STDIN_FILENO)) != srs_success) { - return srs_error_wrap(err, "redirect input"); - } - // should never close the fd 3+, for it myabe used. // for fd should close at exec, use fnctl to set it. diff --git a/trunk/src/app/srs_app_process.hpp b/trunk/src/app/srs_app_process.hpp index 55b574bdd..dceda3cd9 100644 --- a/trunk/src/app/srs_app_process.hpp +++ b/trunk/src/app/srs_app_process.hpp @@ -53,6 +53,9 @@ public: // @param argv the argv for binary path, the argv[0] generally is the binary. // @remark the argv[0] must be the binary. virtual srs_error_t initialize(std::string binary, std::vector argv); +private: + // Redirect standard I/O. + virtual srs_error_t redirect_io(); public: // Start the process, ignore when already started. virtual srs_error_t start(); diff --git a/trunk/src/main/srs_main_server.cpp b/trunk/src/main/srs_main_server.cpp index 99ffb0251..b918c3b47 100644 --- a/trunk/src/main/srs_main_server.cpp +++ b/trunk/src/main/srs_main_server.cpp @@ -119,8 +119,7 @@ srs_error_t do_main(int argc, char** argv) // config already applied to log. srs_trace2(TAG_MAIN, "%s, %s", RTMP_SIG_SRS_SERVER, RTMP_SIG_SRS_LICENSE); - srs_trace("authors: %s", RTMP_SIG_SRS_AUTHORS); - srs_trace("contributors: %s", SRS_CONSTRIBUTORS); + srs_trace("authors: %sand %s", RTMP_SIG_SRS_AUTHORS, SRS_CONSTRIBUTORS); srs_trace("cwd=%s, work_dir=%s, build: %s, configure: %s, uname: %s, osx: %d", _srs_config->cwd().c_str(), cwd.c_str(), SRS_BUILD_DATE, SRS_USER_CONFIGURE, SRS_UNAME, SRS_OSX_BOOL); srs_trace("configure detail: " SRS_CONFIGURE); From 826f5121c5dfafb39ef093c6d587d328942b25f2 Mon Sep 17 00:00:00 2001 From: Haibo Chen Date: Fri, 27 Aug 2021 07:27:33 +0800 Subject: [PATCH 2/3] Support for multiple SPS/PPS, then pick the first one. (#2544) --- trunk/src/kernel/srs_kernel_codec.cpp | 62 ++++++++++++++++----------- trunk/src/utest/srs_utest_kernel.cpp | 16 +++++++ 2 files changed, 54 insertions(+), 24 deletions(-) diff --git a/trunk/src/kernel/srs_kernel_codec.cpp b/trunk/src/kernel/srs_kernel_codec.cpp index 1bb324c12..48a2c96b5 100644 --- a/trunk/src/kernel/srs_kernel_codec.cpp +++ b/trunk/src/kernel/srs_kernel_codec.cpp @@ -806,41 +806,55 @@ srs_error_t SrsFormat::avc_demux_sps_pps(SrsBuffer* stream) } int8_t numOfSequenceParameterSets = stream->read_1bytes(); numOfSequenceParameterSets &= 0x1f; - if (numOfSequenceParameterSets != 1) { + if (numOfSequenceParameterSets < 1) { return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode SPS"); } - if (!stream->require(2)) { - return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode SPS size"); - } - uint16_t sequenceParameterSetLength = stream->read_2bytes(); - if (!stream->require(sequenceParameterSetLength)) { - return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode SPS data"); - } - if (sequenceParameterSetLength > 0) { - vcodec->sequenceParameterSetNALUnit.resize(sequenceParameterSetLength); - stream->read_bytes(&vcodec->sequenceParameterSetNALUnit[0], sequenceParameterSetLength); + // Support for multiple SPS, then pick the first non-empty one. + for (int i = 0; i < numOfSequenceParameterSets; ++i) { + if (!stream->require(2)) { + return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode SPS size"); + } + uint16_t sequenceParameterSetLength = stream->read_2bytes(); + if (!stream->require(sequenceParameterSetLength)) { + return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode SPS data"); + } + if (vcodec->sequenceParameterSetNALUnit.size() > 0) { + stream->skip(sequenceParameterSetLength); + continue; + } + if (sequenceParameterSetLength > 0) { + vcodec->sequenceParameterSetNALUnit.resize(sequenceParameterSetLength); + stream->read_bytes(&vcodec->sequenceParameterSetNALUnit[0], sequenceParameterSetLength); + } } + // 1 pps if (!stream->require(1)) { return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode PPS"); } int8_t numOfPictureParameterSets = stream->read_1bytes(); numOfPictureParameterSets &= 0x1f; - if (numOfPictureParameterSets != 1) { - return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode PPS"); + if (numOfPictureParameterSets < 1) { + return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode SPS"); } - if (!stream->require(2)) { - return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode PPS size"); + // Support for multiple PPS, then pick the first non-empty one. + for (int i = 0; i < numOfPictureParameterSets; ++i) { + if (!stream->require(2)) { + return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode PPS size"); + } + uint16_t pictureParameterSetLength = stream->read_2bytes(); + if (!stream->require(pictureParameterSetLength)) { + return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode PPS data"); + } + if (vcodec->pictureParameterSetNALUnit.size() > 0) { + stream->skip(pictureParameterSetLength); + continue; + } + if (pictureParameterSetLength > 0) { + vcodec->pictureParameterSetNALUnit.resize(pictureParameterSetLength); + stream->read_bytes(&vcodec->pictureParameterSetNALUnit[0], pictureParameterSetLength); + } } - uint16_t pictureParameterSetLength = stream->read_2bytes(); - if (!stream->require(pictureParameterSetLength)) { - return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode PPS data"); - } - if (pictureParameterSetLength > 0) { - vcodec->pictureParameterSetNALUnit.resize(pictureParameterSetLength); - stream->read_bytes(&vcodec->pictureParameterSetNALUnit[0], pictureParameterSetLength); - } - return avc_demux_sps(); } diff --git a/trunk/src/utest/srs_utest_kernel.cpp b/trunk/src/utest/srs_utest_kernel.cpp index e2e93c14c..b613a4963 100644 --- a/trunk/src/utest/srs_utest_kernel.cpp +++ b/trunk/src/utest/srs_utest_kernel.cpp @@ -3723,6 +3723,22 @@ VOID TEST(KernelCodecTest, VideoFormatSepcial) }; HELPER_EXPECT_SUCCESS(f.on_video(0, (char*)buf, sizeof(buf))); } + + if (true) { + SrsFormat f; + HELPER_EXPECT_SUCCESS(f.initialize()); + uint8_t buf[] = { + 0x17, // 1, Keyframe; 7, AVC. + 0x00, // 0, Sequence header. + 0x00, 0x00, 0x00, // Timestamp. + // AVC extra data, SPS/PPS. + 0x00, 0x00, 0x00, 0x00, + 0x00, // lengthSizeMinusOne + 0x02, 0x00, 0x00, 0x00, 0x00, // 2 SPS, + 0x02, 0x00, 0x00, 0x00, 0x00 // 2 PPS, + }; + HELPER_EXPECT_SUCCESS(f.on_video(0, (char*)buf, sizeof(buf))); + } } VOID TEST(KernelCodecTest, VideoFormat) From a7feedabc618dff8ff839263c175327654f04f7b Mon Sep 17 00:00:00 2001 From: Haibo Chen Date: Fri, 27 Aug 2021 07:44:19 +0800 Subject: [PATCH 3/3] Use SrsAsyncCallWorker in http hooks instead, to covert to async call. (#2542) * Use SrsAsyncCallWorker in http hooks instead, to covert to async call. * delete invalid function --- trunk/src/app/srs_app_rtc_conn.cpp | 196 ++++++++++++++++----------- trunk/src/app/srs_app_rtc_conn.hpp | 38 +++++- trunk/src/app/srs_app_rtc_server.cpp | 11 ++ trunk/src/app/srs_app_rtc_server.hpp | 3 + 4 files changed, 162 insertions(+), 86 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index d9b9552a1..1d4bd742b 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -351,6 +351,53 @@ srs_error_t SrsRtcPLIWorker::cycle() return err; } + +SrsRtcAsyncCallOnStop::SrsRtcAsyncCallOnStop(SrsContextId c, SrsRequest * r) +{ + cid = c; + req = r->copy(); +} + +SrsRtcAsyncCallOnStop::~SrsRtcAsyncCallOnStop() +{ + srs_freep(req); +} + +srs_error_t SrsRtcAsyncCallOnStop::call() +{ + srs_error_t err = srs_success; + + if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) { + return err; + } + + // the http hooks will cause context switch, + // so we must copy all hooks for the on_connect may freed. + // @see https://github.com/ossrs/srs/issues/475 + vector hooks; + + if (true) { + SrsConfDirective* conf = _srs_config->get_vhost_on_stop(req->vhost); + + if (!conf) { + return err; + } + + hooks = conf->args; + } + + for (int i = 0; i < (int)hooks.size(); i++) { + std::string url = hooks.at(i); + SrsHttpHooks::on_stop(url, req); + } + + return err; +} + +std::string SrsRtcAsyncCallOnStop::to_string() +{ + return std::string(""); +} SrsRtcPlayStream::SrsRtcPlayStream(SrsRtcConnection* s, const SrsContextId& cid) { @@ -379,9 +426,8 @@ SrsRtcPlayStream::SrsRtcPlayStream(SrsRtcConnection* s, const SrsContextId& cid) SrsRtcPlayStream::~SrsRtcPlayStream() { - // TODO: FIXME: Use SrsAsyncCallWorker in http hooks instead, to covert to async call. if (req_) { - http_hooks_on_stop(); + session_->server_->exec_async_work(new SrsRtcAsyncCallOnStop(cid_, req_)); } // TODO: FIXME: Should not do callback in de-constructor? @@ -871,35 +917,6 @@ srs_error_t SrsRtcPlayStream::do_request_keyframe(uint32_t ssrc, SrsContextId ci return err; } -void SrsRtcPlayStream::http_hooks_on_stop() -{ - if (!_srs_config->get_vhost_http_hooks_enabled(req_->vhost)) { - return; - } - - // the http hooks will cause context switch, - // so we must copy all hooks for the on_connect may freed. - // @see https://github.com/ossrs/srs/issues/475 - vector hooks; - - if (true) { - SrsConfDirective* conf = _srs_config->get_vhost_on_stop(req_->vhost); - - if (!conf) { - return; - } - - hooks = conf->args; - } - - for (int i = 0; i < (int)hooks.size(); i++) { - std::string url = hooks.at(i); - SrsHttpHooks::on_stop(url, req_); - } - - return; -} - SrsRtcPublishRtcpTimer::SrsRtcPublishRtcpTimer(SrsRtcPublishStream* p) : p_(p) { _srs_hybrid->timer1s()->subscribe(this); @@ -979,6 +996,54 @@ srs_error_t SrsRtcPublishTwccTimer::on_timer(srs_utime_t interval) return err; } + +SrsRtcAsyncCallOnUnpublish::SrsRtcAsyncCallOnUnpublish(SrsContextId c, SrsRequest * r) +{ + cid = c; + req = r->copy(); +} + +SrsRtcAsyncCallOnUnpublish::~SrsRtcAsyncCallOnUnpublish() +{ + srs_freep(req); +} + +srs_error_t SrsRtcAsyncCallOnUnpublish::call() +{ + srs_error_t err = srs_success; + + if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) { + return err; + } + + // the http hooks will cause context switch, + // so we must copy all hooks for the on_connect may freed. + // @see https://github.com/ossrs/srs/issues/475 + vector hooks; + + if (true) { + SrsConfDirective* conf = _srs_config->get_vhost_on_unpublish(req->vhost); + + if (!conf) { + return err; + } + + hooks = conf->args; + } + + for (int i = 0; i < (int)hooks.size(); i++) { + std::string url = hooks.at(i); + SrsHttpHooks::on_unpublish(url, req); + } + + return err; +} + +std::string SrsRtcAsyncCallOnUnpublish::to_string() +{ + return std::string(""); +} + SrsRtcPublishStream::SrsRtcPublishStream(SrsRtcConnection* session, const SrsContextId& cid) { cid_ = cid; @@ -988,7 +1053,7 @@ SrsRtcPublishStream::SrsRtcPublishStream(SrsRtcConnection* session, const SrsCon pli_epp = new SrsErrorPithyPrint(); twcc_epp_ = new SrsErrorPithyPrint(3.0); - req = NULL; + req_ = NULL; source = NULL; nn_simulate_nack_drop = 0; nack_enabled_ = false; @@ -1009,8 +1074,8 @@ SrsRtcPublishStream::SrsRtcPublishStream(SrsRtcConnection* session, const SrsCon SrsRtcPublishStream::~SrsRtcPublishStream() { - if (req) { - http_hooks_on_unpublish(); + if (req_) { + session_->server_->exec_async_work(new SrsRtcAsyncCallOnUnpublish(cid_, req_)); } srs_freep(timer_rtcp_); @@ -1027,7 +1092,7 @@ SrsRtcPublishStream::~SrsRtcPublishStream() // it must be called after source stream unpublish (set source stream is_created=false). // if not, it lead to republish failed. if (_srs_rtc_hijacker) { - _srs_rtc_hijacker->on_stop_publish(session_, this, req); + _srs_rtc_hijacker->on_stop_publish(session_, this, req_); } for (int i = 0; i < (int)video_tracks_.size(); ++i) { @@ -1045,7 +1110,7 @@ SrsRtcPublishStream::~SrsRtcPublishStream() srs_freep(pli_worker_); srs_freep(twcc_epp_); srs_freep(pli_epp); - srs_freep(req); + srs_freep(req_); // update the statistic when client coveried. SrsStatistic* stat = SrsStatistic::instance(); @@ -1056,7 +1121,7 @@ srs_error_t SrsRtcPublishStream::initialize(SrsRequest* r, SrsRtcSourceDescripti { srs_error_t err = srs_success; - req = r->copy(); + req_ = r->copy(); if (stream_desc->audio_track_desc_) { audio_tracks_.push_back(new SrsRtcAudioRecvTrack(session_, stream_desc->audio_track_desc_)); @@ -1083,10 +1148,10 @@ srs_error_t SrsRtcPublishStream::initialize(SrsRequest* r, SrsRtcSourceDescripti rtcp_twcc_.set_media_ssrc(media_ssrc); } - nack_enabled_ = _srs_config->get_rtc_nack_enabled(req->vhost); - nack_no_copy_ = _srs_config->get_rtc_nack_no_copy(req->vhost); - pt_to_drop_ = (uint16_t)_srs_config->get_rtc_drop_for_pt(req->vhost); - twcc_enabled_ = _srs_config->get_rtc_twcc_enabled(req->vhost); + nack_enabled_ = _srs_config->get_rtc_nack_enabled(req_->vhost); + nack_no_copy_ = _srs_config->get_rtc_nack_no_copy(req_->vhost); + pt_to_drop_ = (uint16_t)_srs_config->get_rtc_drop_for_pt(req_->vhost); + twcc_enabled_ = _srs_config->get_rtc_twcc_enabled(req_->vhost); // No TWCC when negotiate, disable it. if (twcc_id <= 0) { @@ -1107,14 +1172,14 @@ srs_error_t SrsRtcPublishStream::initialize(SrsRequest* r, SrsRtcSourceDescripti } // Setup the publish stream in source to enable PLI as such. - if ((err = _srs_rtc_sources->fetch_or_create(req, &source)) != srs_success) { + if ((err = _srs_rtc_sources->fetch_or_create(req_, &source)) != srs_success) { return srs_error_wrap(err, "create source"); } source->set_publish_stream(this); // Bridge to rtmp #if defined(SRS_RTC) && defined(SRS_FFMPEG_FIT) - bool rtc_to_rtmp = _srs_config->get_rtc_to_rtmp(req->vhost); + bool rtc_to_rtmp = _srs_config->get_rtc_to_rtmp(req_->vhost); if (rtc_to_rtmp) { SrsLiveSource *rtmp = NULL; if ((err = _srs_sources->fetch_or_create(r, _srs_hybrid->srs()->instance(), &rtmp)) != srs_success) { @@ -1160,14 +1225,14 @@ srs_error_t SrsRtcPublishStream::start() } if (_srs_rtc_hijacker) { - if ((err = _srs_rtc_hijacker->on_start_publish(session_, this, req)) != srs_success) { + if ((err = _srs_rtc_hijacker->on_start_publish(session_, this, req_)) != srs_success) { return srs_error_wrap(err, "on start publish"); } } // update the statistic when client discoveried. SrsStatistic* stat = SrsStatistic::instance(); - if ((err = stat->on_client(cid_.c_str(), req, session_, SrsRtcConnPublish)) != srs_success) { + if ((err = stat->on_client(cid_.c_str(), req_, session_, SrsRtcConnPublish)) != srs_success) { return srs_error_wrap(err, "rtc: stat client"); } @@ -1385,7 +1450,7 @@ srs_error_t SrsRtcPublishStream::do_on_rtp_plaintext(SrsRtpPacket*& pkt, SrsBuff } if (_srs_rtc_hijacker) { - if ((err = _srs_rtc_hijacker->on_rtp_packet(session_, this, req, pkt)) != srs_success) { + if ((err = _srs_rtc_hijacker->on_rtp_packet(session_, this, req_, pkt)) != srs_success) { return srs_error_wrap(err, "on rtp packet"); } } @@ -1677,33 +1742,6 @@ void SrsRtcPublishStream::update_send_report_time(uint32_t ssrc, const SrsNtp& n } } -void SrsRtcPublishStream::http_hooks_on_unpublish() -{ - if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) { - return; - } - - // the http hooks will cause context switch, - // so we must copy all hooks for the on_connect may freed. - // @see https://github.com/ossrs/srs/issues/475 - vector hooks; - - if (true) { - SrsConfDirective* conf = _srs_config->get_vhost_on_unpublish(req->vhost); - - if (!conf) { - return; - } - - hooks = conf->args; - } - - for (int i = 0; i < (int)hooks.size(); i++) { - std::string url = hooks.at(i); - SrsHttpHooks::on_unpublish(url, req); - } -} - ISrsRtcConnectionHijacker::ISrsRtcConnectionHijacker() { } @@ -1753,7 +1791,7 @@ srs_error_t SrsRtcConnectionNackTimer::on_timer(srs_utime_t interval) SrsRtcConnection::SrsRtcConnection(SrsRtcServer* s, const SrsContextId& cid) { - req = NULL; + req_ = NULL; cid_ = cid; hijacker_ = NULL; @@ -1820,7 +1858,7 @@ SrsRtcConnection::~SrsRtcConnection() srs_freep(cache_buffer_); srs_freep(transport_); - srs_freep(req); + srs_freep(req_); srs_freep(pp_address_change); srs_freep(pli_epp); } @@ -2019,7 +2057,7 @@ srs_error_t SrsRtcConnection::initialize(SrsRequest* r, bool dtls, bool srtp, st srs_error_t err = srs_success; username_ = username; - req = r->copy(); + req_ = r->copy(); if (!srtp) { srs_freep(transport_); @@ -2036,10 +2074,10 @@ srs_error_t SrsRtcConnection::initialize(SrsRequest* r, bool dtls, bool srtp, st } // TODO: FIXME: Support reload. - session_timeout = _srs_config->get_rtc_stun_timeout(req->vhost); + session_timeout = _srs_config->get_rtc_stun_timeout(req_->vhost); last_stun_time = srs_get_system_time(); - nack_enabled_ = _srs_config->get_rtc_nack_enabled(req->vhost); + nack_enabled_ = _srs_config->get_rtc_nack_enabled(req_->vhost); srs_trace("RTC init session, user=%s, url=%s, encrypt=%u/%u, DTLS(role=%s, version=%s), timeout=%dms, nack=%d", username.c_str(), r->get_stream_url().c_str(), dtls, srtp, cfg->dtls_role.c_str(), cfg->dtls_version.c_str(), @@ -2666,7 +2704,7 @@ srs_error_t SrsRtcConnection::on_binding_request(SrsStunPacket* r) ++_srs_pps_sstuns->sugar; - bool strict_check = _srs_config->get_rtc_stun_strict_check(req->vhost); + bool strict_check = _srs_config->get_rtc_stun_strict_check(req_->vhost); if (strict_check && r->get_ice_controlled()) { // @see: https://tools.ietf.org/html/draft-ietf-ice-rfc5245bis-00#section-6.1.3.1 // TODO: Send 487 (Role Conflict) error response. diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index ae968ba75..17e5a7155 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -195,6 +196,20 @@ public: virtual srs_error_t cycle(); }; +// the rtc on_stop async call. +class SrsRtcAsyncCallOnStop : public ISrsAsyncCallTask +{ +private: + SrsContextId cid; + SrsRequest* req; +public: + SrsRtcAsyncCallOnStop(SrsContextId c, SrsRequest* r); + virtual ~SrsRtcAsyncCallOnStop(); +public: + virtual srs_error_t call(); + virtual std::string to_string(); +}; + // A RTC play stream, client pull and play stream from SRS. class SrsRtcPlayStream : public ISrsCoroutineHandler, public ISrsReloadHandler , public ISrsRtcPLIWorkerHandler, public ISrsRtcSourceChangeCallback @@ -264,8 +279,6 @@ private: // Interface ISrsRtcPLIWorkerHandler public: virtual srs_error_t do_request_keyframe(uint32_t ssrc, SrsContextId cid); -private: - virtual void http_hooks_on_stop(); }; // A fast timer for publish stream, for RTCP feedback. @@ -294,6 +307,20 @@ private: srs_error_t on_timer(srs_utime_t interval); }; +// the rtc on_unpublish async call. +class SrsRtcAsyncCallOnUnpublish : public ISrsAsyncCallTask +{ +private: + SrsContextId cid; + SrsRequest* req; +public: + SrsRtcAsyncCallOnUnpublish(SrsContextId c, SrsRequest* r); + virtual ~SrsRtcAsyncCallOnUnpublish(); +public: + virtual srs_error_t call(); + virtual std::string to_string(); +}; + // A RTC publish stream, client push and publish stream to SRS. class SrsRtcPublishStream : public ISrsRtspPacketDecodeHandler , public ISrsRtcPublishStream, public ISrsRtcPLIWorkerHandler @@ -319,7 +346,7 @@ private: bool request_keyframe_; SrsErrorPithyPrint* pli_epp; private: - SrsRequest* req; + SrsRequest* req_; SrsRtcSource* source; // Simulators. int nn_simulate_nack_drop; @@ -377,8 +404,6 @@ private: SrsRtcVideoRecvTrack* get_video_track(uint32_t ssrc); void update_rtt(uint32_t ssrc, int rtt); void update_send_report_time(uint32_t ssrc, const SrsNtp& ntp, uint32_t rtp_time); -private: - virtual void http_hooks_on_unpublish(); }; // Callback for RTC connection. @@ -451,8 +476,7 @@ private: private: // For each RTC session, we use a specified cid for debugging logs. SrsContextId cid_; - // TODO: FIXME: Rename to req_. - SrsRequest* req; + SrsRequest* req_; SrsSdp remote_sdp; SrsSdp local_sdp; private: diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp index 62b9a418c..8a77428d9 100644 --- a/trunk/src/app/srs_app_rtc_server.cpp +++ b/trunk/src/app/srs_app_rtc_server.cpp @@ -243,6 +243,7 @@ SrsRtcServer::SrsRtcServer() { handler = NULL; hijacker = NULL; + async = new SrsAsyncCallWorker(); _srs_config->subscribe(this); } @@ -258,6 +259,9 @@ SrsRtcServer::~SrsRtcServer() srs_freep(listener); } } + + async->stop(); + srs_freep(async); } srs_error_t SrsRtcServer::initialize() @@ -273,6 +277,8 @@ srs_error_t SrsRtcServer::initialize() return srs_error_wrap(err, "black hole"); } + async->start(); + return err; } @@ -289,6 +295,11 @@ void SrsRtcServer::set_handler(ISrsRtcServerHandler* h) void SrsRtcServer::set_hijacker(ISrsRtcServerHijacker* h) { hijacker = h; +} + +srs_error_t SrsRtcServer::exec_async_work(ISrsAsyncCallTask * t) +{ + return async->execute(t); } srs_error_t SrsRtcServer::listen_udp() diff --git a/trunk/src/app/srs_app_rtc_server.hpp b/trunk/src/app/srs_app_rtc_server.hpp index d90ed6e7c..f138e4638 100644 --- a/trunk/src/app/srs_app_rtc_server.hpp +++ b/trunk/src/app/srs_app_rtc_server.hpp @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -94,6 +95,7 @@ private: std::vector listeners; ISrsRtcServerHandler* handler; ISrsRtcServerHijacker* hijacker; + SrsAsyncCallWorker* async; public: SrsRtcServer(); virtual ~SrsRtcServer(); @@ -106,6 +108,7 @@ public: // Set the handler for server events. void set_handler(ISrsRtcServerHandler* h); void set_hijacker(ISrsRtcServerHijacker* h); + srs_error_t exec_async_work(ISrsAsyncCallTask* t); public: // TODO: FIXME: Support gracefully quit. // TODO: FIXME: Support reload.