diff --git a/README.md b/README.md index 498d42045c..ccf38a4a77 100755 --- a/README.md +++ b/README.md @@ -336,6 +336,7 @@ Remark: ## History +* v2.0, 2017-04-15, Fix [#844][bug #844], support Haivision encoder. 2.0.238 * v2.0, 2017-04-15, Merge [#846][bug #846], fix fd leak for FLV stream caster. 2.0.237 * v2.0, 2017-04-15, Merge [#841][bug #841], avoid the duplicated sps/pps in ts. 2.0.236 * v2.0, 2017-04-09, Fix [#834][bug #834], crash for TS context corrupt. 2.0.235 @@ -1285,6 +1286,7 @@ Winlin [bug #834]: https://github.com/ossrs/srs/issues/834 [bug #841]: https://github.com/ossrs/srs/issues/841 [bug #846]: https://github.com/ossrs/srs/issues/846 +[bug #844]: https://github.com/ossrs/srs/issues/844 [bug #xxxxxxxxxx]: https://github.com/ossrs/srs/issues/xxxxxxxxxx [exo #828]: https://github.com/google/ExoPlayer/pull/828 diff --git a/trunk/src/app/srs_app_rtmp_conn.cpp b/trunk/src/app/srs_app_rtmp_conn.cpp index 637b529958..a256ed3d18 100755 --- a/trunk/src/app/srs_app_rtmp_conn.cpp +++ b/trunk/src/app/srs_app_rtmp_conn.cpp @@ -546,6 +546,16 @@ int SrsRtmpConn::stream_service_cycle() return publishing(source); } + case SrsRtmpConnHaivisionPublish: { + srs_verbose("Haivision start to publish stream %s.", req->stream.c_str()); + + if ((ret = rtmp->start_haivision_publish(res->stream_id)) != ERROR_SUCCESS) { + srs_error("start to publish stream failed. ret=%d", ret); + return ret; + } + + return publishing(source); + } case SrsRtmpConnFlashPublish: { srs_verbose("flash start to publish stream %s.", req->stream.c_str()); @@ -839,7 +849,7 @@ int SrsRtmpConn::publishing(SrsSource* source) // @see: https://github.com/ossrs/srs/issues/237 SrsPublishRecvThread trd(rtmp, req, st_netfd_fileno(stfd), 0, this, source, - client_type == SrsRtmpConnFMLEPublish, + client_type != SrsRtmpConnFlashPublish, vhost_is_edge); srs_info("start to publish stream %s success", req->stream.c_str()); diff --git a/trunk/src/app/srs_app_security.cpp b/trunk/src/app/srs_app_security.cpp index bf1c57ea88..213531d896 100644 --- a/trunk/src/app/srs_app_security.cpp +++ b/trunk/src/app/srs_app_security.cpp @@ -90,6 +90,7 @@ int SrsSecurity::allow_check(SrsConfDirective* rules, SrsRtmpConnType type, std: break; case SrsRtmpConnFMLEPublish: case SrsRtmpConnFlashPublish: + case SrsRtmpConnHaivisionPublish: if (rule->arg0() != "publish") { break; } @@ -135,6 +136,7 @@ int SrsSecurity::deny_check(SrsConfDirective* rules, SrsRtmpConnType type, std:: break; case SrsRtmpConnFMLEPublish: case SrsRtmpConnFlashPublish: + case SrsRtmpConnHaivisionPublish: if (rule->arg0() != "publish") { break; } diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index ad50f1384b..ddd41e59d8 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // current release version #define VERSION_MAJOR 2 #define VERSION_MINOR 0 -#define VERSION_REVISION 237 +#define VERSION_REVISION 238 // generated by configure, only macros. #include diff --git a/trunk/src/protocol/srs_rtmp_stack.cpp b/trunk/src/protocol/srs_rtmp_stack.cpp index 9696357f81..0c929d94cf 100644 --- a/trunk/src/protocol/srs_rtmp_stack.cpp +++ b/trunk/src/protocol/srs_rtmp_stack.cpp @@ -1791,6 +1791,7 @@ string srs_client_type_string(SrsRtmpConnType type) case SrsRtmpConnPlay: return "Play"; case SrsRtmpConnFlashPublish: return "flash-publish"; case SrsRtmpConnFMLEPublish: return "fmle-publish"; + case SrsRtmpConnHaivisionPublish: return "haivision-publish"; default: return "Unknown"; } } @@ -2693,6 +2694,14 @@ int SrsRtmpServer::identify_client(int stream_id, SrsRtmpConnType& type, string& } return ret; } + + // For encoder of Haivision, it always send a _checkbw call message. + // @Remark the next message is createStream, so we continue to identify it. + // @see https://github.com/ossrs/srs/issues/844 + if (call->command_name == "_checkbw") { + srs_info("Haivision encoder identified."); + continue; + } continue; } @@ -2968,6 +2977,60 @@ int SrsRtmpServer::start_fmle_publish(int stream_id) return ret; } +int SrsRtmpServer::start_haivision_publish(int stream_id) +{ + int ret = ERROR_SUCCESS; + + // publish + if (true) { + SrsCommonMessage* msg = NULL; + SrsPublishPacket* pkt = NULL; + if ((ret = expect_message(&msg, &pkt)) != ERROR_SUCCESS) { + srs_error("recv publish message failed. ret=%d", ret); + return ret; + } + srs_info("recv publish request message success."); + + SrsAutoFree(SrsCommonMessage, msg); + SrsAutoFree(SrsPublishPacket, pkt); + } + + // publish response onFCPublish(NetStream.Publish.Start) + if (true) { + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); + + pkt->command_name = RTMP_AMF0_COMMAND_ON_FC_PUBLISH; + pkt->data->set(StatusCode, SrsAmf0Any::str(StatusCodePublishStart)); + pkt->data->set(StatusDescription, SrsAmf0Any::str("Started publishing stream.")); + + if ((ret = protocol->send_and_free_packet(pkt, stream_id)) != ERROR_SUCCESS) { + srs_error("send onFCPublish(NetStream.Publish.Start) message failed. ret=%d", ret); + return ret; + } + srs_info("send onFCPublish(NetStream.Publish.Start) message success."); + } + + // publish response onStatus(NetStream.Publish.Start) + if (true) { + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); + + pkt->data->set(StatusLevel, SrsAmf0Any::str(StatusLevelStatus)); + pkt->data->set(StatusCode, SrsAmf0Any::str(StatusCodePublishStart)); + pkt->data->set(StatusDescription, SrsAmf0Any::str("Started publishing stream.")); + pkt->data->set(StatusClientId, SrsAmf0Any::str(RTMP_SIG_CLIENT_ID)); + + if ((ret = protocol->send_and_free_packet(pkt, stream_id)) != ERROR_SUCCESS) { + srs_error("send onStatus(NetStream.Publish.Start) message failed. ret=%d", ret); + return ret; + } + srs_info("send onStatus(NetStream.Publish.Start) message success."); + } + + srs_info("Haivision publish success."); + + return ret; +} + int SrsRtmpServer::fmle_unpublish(int stream_id, double unpublish_tid) { int ret = ERROR_SUCCESS; @@ -3102,6 +3165,10 @@ int SrsRtmpServer::identify_create_stream_client(SrsCreateStreamPacket* req, int srs_info("identify client by create stream, play or flash publish."); return identify_create_stream_client(dynamic_cast(pkt), stream_id, type, stream_name, duration); } + if (dynamic_cast(pkt)) { + srs_info("identify client by FCPublish, haivision publish."); + return identify_haivision_publish_client(dynamic_cast(pkt), type, stream_name); + } srs_trace("ignore AMF0/AMF3 command message."); } @@ -3129,6 +3196,26 @@ int SrsRtmpServer::identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsRtmp return ret; } +int SrsRtmpServer::identify_haivision_publish_client(SrsFMLEStartPacket* req, SrsRtmpConnType& type, string& stream_name) +{ + int ret = ERROR_SUCCESS; + + type = SrsRtmpConnHaivisionPublish; + stream_name = req->stream_name; + + // FCPublish response + if (true) { + SrsFMLEStartResPacket* pkt = new SrsFMLEStartResPacket(req->transaction_id); + if ((ret = protocol->send_and_free_packet(pkt, 0)) != ERROR_SUCCESS) { + srs_error("send FCPublish response message failed. ret=%d", ret); + return ret; + } + srs_info("send FCPublish response message success."); + } + + return ret; +} + int SrsRtmpServer::identify_flash_publish_client(SrsPublishPacket* req, SrsRtmpConnType& type, string& stream_name) { int ret = ERROR_SUCCESS; diff --git a/trunk/src/protocol/srs_rtmp_stack.hpp b/trunk/src/protocol/srs_rtmp_stack.hpp index fdd8a10513..3c8d3edf95 100644 --- a/trunk/src/protocol/srs_rtmp_stack.hpp +++ b/trunk/src/protocol/srs_rtmp_stack.hpp @@ -69,6 +69,7 @@ class SrsCommonMessage; class SrsPacket; class SrsAmf0Object; class IMergeReadHandler; +class SrsCallPacket; /**************************************************************************** ***************************************************************************** @@ -631,6 +632,7 @@ enum SrsRtmpConnType SrsRtmpConnPlay, SrsRtmpConnFMLEPublish, SrsRtmpConnFlashPublish, + SrsRtmpConnHaivisionPublish, }; std::string srs_client_type_string(SrsRtmpConnType type); bool srs_client_type_is_publish(SrsRtmpConnType type); @@ -989,6 +991,11 @@ class SrsRtmpServer * onStatus(NetStream.Publish.Start) */ virtual int start_fmle_publish(int stream_id); + /** + * For encoder of Haivision, response the startup request. + * @see https://github.com/ossrs/srs/issues/844 + */ + virtual int start_haivision_publish(int stream_id); /** * process the FMLE unpublish event. * @unpublish_tid the unpublish request transaction id. @@ -1025,6 +1032,7 @@ class SrsRtmpServer private: virtual int identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsRtmpConnType& type, std::string& stream_name, double& duration); virtual int identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsRtmpConnType& type, std::string& stream_name); + virtual int identify_haivision_publish_client(SrsFMLEStartPacket* req, SrsRtmpConnType& type, std::string& stream_name); virtual int identify_flash_publish_client(SrsPublishPacket* req, SrsRtmpConnType& type, std::string& stream_name); private: virtual int identify_play_client(SrsPlayPacket* req, SrsRtmpConnType& type, std::string& stream_name, double& duration); @@ -1293,7 +1301,7 @@ class SrsCloseStreamPacket : public SrsPacket }; /** -* FMLE start publish: ReleaseStream/PublishStream +* FMLE start publish: ReleaseStream/PublishStream/FCPublish/FCUnpublish */ class SrsFMLEStartPacket : public SrsPacket {