diff --git a/README.md b/README.md index 7761130e7..59145be97 100755 --- a/README.md +++ b/README.md @@ -26,9 +26,12 @@ Compare:
* nginx v1.5.0: 139524 lines
Features:
+* v0.2, 2013-10-23, v0.2 released. +* v0.2, 2013-10-25, support flash publish. * v0.2, 2013-10-25, support h264/avc codec by rtmp complex handshake(SrsComplexHandshake). * v0.2, 2013-10-24, support time jitter detect and correct algorithm(SrsConsumer::jitter_correct). -* v0.2, 2013-10-24, support decode the video/audio codec type(SrsCodec), cache the h264/avc sequence header. +* v0.2, 2013-10-24, support decode codec type(SrsCodec) to cache the h264/avc sequence header. +* v0.1, 2013-10-23, v0.1 released. * v0.1, 2013-10-23, support basic amf0 codec, simplify the api using c-style api. * v0.1, 2013-10-23, support shared ptr msg(SrsSharedPtrMessage) for zero memory copy. * v0.1, 2013-10-22, support vp6 codec with rtmp protocol specified simple handshake. diff --git a/trunk/src/core/srs_core_client.cpp b/trunk/src/core/srs_core_client.cpp index a98909858..a563f8afd 100755 --- a/trunk/src/core/srs_core_client.cpp +++ b/trunk/src/core/srs_core_client.cpp @@ -137,15 +137,25 @@ int SrsClient::do_cycle() srs_info("start to play stream %s success", req->stream.c_str()); return streaming_play(source); } - case SrsClientPublish: { - srs_verbose("start to publish stream %s.", req->stream.c_str()); + case SrsClientFMLEPublish: { + srs_verbose("FMLE start to publish stream %s.", req->stream.c_str()); - if ((ret = rtmp->start_publish(res->stream_id)) != ERROR_SUCCESS) { + if ((ret = rtmp->start_fmle_publish(res->stream_id)) != ERROR_SUCCESS) { srs_error("start to publish stream failed. ret=%d", ret); return ret; } srs_info("start to publish stream %s success", req->stream.c_str()); - return streaming_publish(source); + return streaming_publish(source, true); + } + case SrsClientFlashPublish: { + srs_verbose("flash start to publish stream %s.", req->stream.c_str()); + + if ((ret = rtmp->start_flash_publish(res->stream_id)) != ERROR_SUCCESS) { + srs_error("flash start to publish stream failed. ret=%d", ret); + return ret; + } + srs_info("flash start to publish stream %s success", req->stream.c_str()); + return streaming_publish(source, false); } default: { ret = ERROR_SYSTEM_CLIENT_INVALID; @@ -237,7 +247,7 @@ int SrsClient::streaming_play(SrsSource* source) return ret; } -int SrsClient::streaming_publish(SrsSource* source) +int SrsClient::streaming_publish(SrsSource* source, bool is_fmle) { int ret = ERROR_SUCCESS; @@ -292,6 +302,12 @@ int SrsClient::streaming_publish(SrsSource* source) srs_error("decode unpublish message failed. ret=%d", ret); return ret; } + + // flash unpublish. + if (!is_fmle) { + srs_trace("flash publish finished."); + return ret; + } SrsPacket* pkt = msg->get_packet(); if (dynamic_cast(pkt)) { diff --git a/trunk/src/core/srs_core_client.hpp b/trunk/src/core/srs_core_client.hpp index f0062751a..cc2cad914 100755 --- a/trunk/src/core/srs_core_client.hpp +++ b/trunk/src/core/srs_core_client.hpp @@ -54,7 +54,7 @@ protected: virtual int do_cycle(); private: virtual int streaming_play(SrsSource* source); - virtual int streaming_publish(SrsSource* source); + virtual int streaming_publish(SrsSource* source, bool is_fmle); virtual int get_peer_ip(); }; diff --git a/trunk/src/core/srs_core_protocol.cpp b/trunk/src/core/srs_core_protocol.cpp index 350ce3958..05b2e690d 100755 --- a/trunk/src/core/srs_core_protocol.cpp +++ b/trunk/src/core/srs_core_protocol.cpp @@ -1792,7 +1792,7 @@ int SrsPublishPacket::decode(SrsStream* stream) return ret; } - if ((ret = srs_amf0_read_string(stream, type)) != ERROR_SUCCESS) { + if (!stream->empty() && (ret = srs_amf0_read_string(stream, type)) != ERROR_SUCCESS) { srs_error("amf0 decode publish type failed. ret=%d", ret); return ret; } diff --git a/trunk/src/core/srs_core_protocol.hpp b/trunk/src/core/srs_core_protocol.hpp index 6549c4d9e..5628762a6 100755 --- a/trunk/src/core/srs_core_protocol.hpp +++ b/trunk/src/core/srs_core_protocol.hpp @@ -623,6 +623,7 @@ public: double transaction_id; SrsAmf0Null* command_object; std::string stream_name; + // optional, default to live. std::string type; public: SrsPublishPacket(); diff --git a/trunk/src/core/srs_core_rtmp.cpp b/trunk/src/core/srs_core_rtmp.cpp index f98726c58..e8a4e8fa8 100755 --- a/trunk/src/core/srs_core_rtmp.cpp +++ b/trunk/src/core/srs_core_rtmp.cpp @@ -395,7 +395,6 @@ int SrsRtmp::identify_client(int stream_id, SrsClientType& type, std::string& st return identify_fmle_publish_client( dynamic_cast(pkt), type, stream_name); } - // TODO: identify the flash publish client. srs_trace("ignore AMF0/AMF3 command message."); } @@ -517,7 +516,7 @@ int SrsRtmp::start_play(int stream_id) return ret; } -int SrsRtmp::start_publish(int stream_id) +int SrsRtmp::start_fmle_publish(int stream_id) { int ret = ERROR_SUCCESS; @@ -625,6 +624,8 @@ int SrsRtmp::start_publish(int stream_id) srs_info("send onStatus(NetStream.Publish.Start) message success."); } + srs_info("FMLE publish success."); + return ret; } @@ -686,6 +687,34 @@ int SrsRtmp::fmle_unpublish(int stream_id, double unpublish_tid) return ret; } +int SrsRtmp::start_flash_publish(int stream_id) +{ + int ret = ERROR_SUCCESS; + + // publish response onStatus(NetStream.Publish.Start) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); + + pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); + pkt->data->set(StatusCode, new SrsAmf0String(StatusCodePublishStart)); + pkt->data->set(StatusDescription, new SrsAmf0String("Started publishing stream.")); + pkt->data->set(StatusClientId, new SrsAmf0String(RTMP_SIG_CLIENT_ID)); + + msg->set_packet(pkt, stream_id); + + if ((ret = protocol->send_message(msg)) != 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("flash publish success."); + + return ret; +} + int SrsRtmp::identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, std::string& stream_name) { int ret = ERROR_SUCCESS; @@ -731,6 +760,11 @@ int SrsRtmp::identify_create_stream_client(SrsCreateStreamPacket* req, int strea srs_trace("identity client type=play, stream_name=%s", stream_name.c_str()); return ret; } + if (dynamic_cast(pkt)) { + srs_info("identify client by publish, falsh publish."); + return identify_flash_publish_client( + dynamic_cast(pkt), type, stream_name); + } srs_trace("ignore AMF0/AMF3 command message."); } @@ -742,7 +776,7 @@ int SrsRtmp::identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsClientType { int ret = ERROR_SUCCESS; - type = SrsClientPublish; + type = SrsClientFMLEPublish; stream_name = req->stream_name; // releaseStream response @@ -762,3 +796,13 @@ int SrsRtmp::identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsClientType return ret; } +int SrsRtmp::identify_flash_publish_client(SrsPublishPacket* req, SrsClientType& type, std::string& stream_name) +{ + int ret = ERROR_SUCCESS; + + type = SrsClientFlashPublish; + stream_name = req->stream_name; + + return ret; +} + diff --git a/trunk/src/core/srs_core_rtmp.hpp b/trunk/src/core/srs_core_rtmp.hpp index def9727e8..e9608392f 100755 --- a/trunk/src/core/srs_core_rtmp.hpp +++ b/trunk/src/core/srs_core_rtmp.hpp @@ -40,6 +40,7 @@ class SrsCommonMessage; class SrsCreateStreamPacket; class SrsFMLEStartPacket; class SrsComplexHandshake; +class SrsPublishPacket; /** * the original request from client. @@ -85,7 +86,8 @@ enum SrsClientType { SrsClientUnknown, SrsClientPlay, - SrsClientPublish, + SrsClientFMLEPublish, + SrsClientFlashPublish, }; /** @@ -146,15 +148,21 @@ public: * onFCPublish(NetStream.Publish.Start) * onStatus(NetStream.Publish.Start) */ - virtual int start_publish(int stream_id); + virtual int start_fmle_publish(int stream_id); /** * process the FMLE unpublish event. * @unpublish_tid the unpublish request transaction id. */ virtual int fmle_unpublish(int stream_id, double unpublish_tid); + /** + * when client type is publish, response with packets: + * onStatus(NetStream.Publish.Start) + */ + virtual int start_flash_publish(int stream_id); private: virtual int identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, std::string& stream_name); virtual int identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsClientType& type, std::string& stream_name); + virtual int identify_flash_publish_client(SrsPublishPacket* req, SrsClientType& type, std::string& stream_name); }; #endif \ No newline at end of file