正在显示
10 个修改的文件
包含
176 行增加
和
28 行删除
| @@ -25,4 +25,16 @@ Compare:<br/> | @@ -25,4 +25,16 @@ Compare:<br/> | ||
| 25 | * nginx-rtmp v1.0.4: 26786 lines <br/> | 25 | * nginx-rtmp v1.0.4: 26786 lines <br/> |
| 26 | * nginx v1.5.0: 139524 lines <br/> | 26 | * nginx v1.5.0: 139524 lines <br/> |
| 27 | 27 | ||
| 28 | +Features:<br/> | ||
| 29 | +* v0.2, 2013-10-25, support h264/avc codec by rtmp complex handshake(SrsComplexHandshake). | ||
| 30 | +* v0.2, 2013-10-24, support time jitter detect and correct algorithm(SrsConsumer::jitter_correct). | ||
| 31 | +* v0.2, 2013-10-24, support decode the video/audio codec type(SrsCodec), cache the h264/avc sequence header. | ||
| 32 | +* v0.1, 2013-10-23, support basic amf0 codec, simplify the api using c-style api. | ||
| 33 | +* v0.1, 2013-10-23, support shared ptr msg(SrsSharedPtrMessage) for zero memory copy. | ||
| 34 | +* v0.1, 2013-10-22, support vp6 codec with rtmp protocol specified simple handshake. | ||
| 35 | +* v0.1, 2013-10-20, support multiple flash client play live streaming. | ||
| 36 | +* v0.1, 2013-10-20, support FMLE/FFMPEG publish live streaming. | ||
| 37 | +* v0.1, 2013-10-18, support rtmp message2chunk protocol(send message). | ||
| 38 | +* v0.1, 2013-10-17, support rtmp chunk2message protocol(recv message). | ||
| 39 | + | ||
| 28 | Winlin | 40 | Winlin |
| @@ -86,7 +86,8 @@ MODULE_FILES=("srs_core" "srs_core_log" "srs_core_server" | @@ -86,7 +86,8 @@ MODULE_FILES=("srs_core" "srs_core_log" "srs_core_server" | ||
| 86 | "srs_core_error" "srs_core_conn" "srs_core_client" | 86 | "srs_core_error" "srs_core_conn" "srs_core_client" |
| 87 | "srs_core_rtmp" "srs_core_socket" "srs_core_buffer" | 87 | "srs_core_rtmp" "srs_core_socket" "srs_core_buffer" |
| 88 | "srs_core_auto_free" "srs_core_protocol" "srs_core_amf0" | 88 | "srs_core_auto_free" "srs_core_protocol" "srs_core_amf0" |
| 89 | - "srs_core_stream" "srs_core_source" "srs_core_codec") | 89 | + "srs_core_stream" "srs_core_source" "srs_core_codec" |
| 90 | + "srs_core_complex_handshake") | ||
| 90 | MODULE_DIR="src/core" . auto/modules.sh | 91 | MODULE_DIR="src/core" . auto/modules.sh |
| 91 | CORE_OBJS="${MODULE_OBJS[@]}" | 92 | CORE_OBJS="${MODULE_OBJS[@]}" |
| 92 | 93 |
| 1 | +/* | ||
| 2 | +The MIT License (MIT) | ||
| 3 | + | ||
| 4 | +Copyright (c) 2013 winlin | ||
| 5 | + | ||
| 6 | +Permission is hereby granted, free of charge, to any person obtaining a copy of | ||
| 7 | +this software and associated documentation files (the "Software"), to deal in | ||
| 8 | +the Software without restriction, including without limitation the rights to | ||
| 9 | +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||
| 10 | +the Software, and to permit persons to whom the Software is furnished to do so, | ||
| 11 | +subject to the following conditions: | ||
| 12 | + | ||
| 13 | +The above copyright notice and this permission notice shall be included in all | ||
| 14 | +copies or substantial portions of the Software. | ||
| 15 | + | ||
| 16 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||
| 18 | +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||
| 19 | +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||
| 20 | +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
| 21 | +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 22 | +*/ | ||
| 23 | + | ||
| 24 | +#include <srs_core_complex_handshake.hpp> | ||
| 25 | + | ||
| 26 | +#include <srs_core_error.hpp> | ||
| 27 | + | ||
| 28 | +SrsComplexHandshake::SrsComplexHandshake() | ||
| 29 | +{ | ||
| 30 | +} | ||
| 31 | + | ||
| 32 | +SrsComplexHandshake::~SrsComplexHandshake() | ||
| 33 | +{ | ||
| 34 | +} | ||
| 35 | + | ||
| 36 | +int SrsComplexHandshake::handshake(SrsSocket& skt, char* c1) | ||
| 37 | +{ | ||
| 38 | + int ret = ERROR_SUCCESS; | ||
| 39 | + return ret; | ||
| 40 | +} | ||
| 41 | + |
| 1 | +/* | ||
| 2 | +The MIT License (MIT) | ||
| 3 | + | ||
| 4 | +Copyright (c) 2013 winlin | ||
| 5 | + | ||
| 6 | +Permission is hereby granted, free of charge, to any person obtaining a copy of | ||
| 7 | +this software and associated documentation files (the "Software"), to deal in | ||
| 8 | +the Software without restriction, including without limitation the rights to | ||
| 9 | +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||
| 10 | +the Software, and to permit persons to whom the Software is furnished to do so, | ||
| 11 | +subject to the following conditions: | ||
| 12 | + | ||
| 13 | +The above copyright notice and this permission notice shall be included in all | ||
| 14 | +copies or substantial portions of the Software. | ||
| 15 | + | ||
| 16 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||
| 18 | +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||
| 19 | +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||
| 20 | +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
| 21 | +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 22 | +*/ | ||
| 23 | + | ||
| 24 | +#ifndef SRS_CORE_COMPLEX_HANDSHKAE_HPP | ||
| 25 | +#define SRS_CORE_COMPLEX_HANDSHKAE_HPP | ||
| 26 | + | ||
| 27 | +/* | ||
| 28 | +#include <srs_core_complex_handshake.hpp> | ||
| 29 | +*/ | ||
| 30 | + | ||
| 31 | +#include <srs_core.hpp> | ||
| 32 | + | ||
| 33 | +class SrsSocket; | ||
| 34 | + | ||
| 35 | +/** | ||
| 36 | +* rtmp complex handshake, | ||
| 37 | +* @see also crtmp(crtmpserver) or librtmp, | ||
| 38 | +* @see also: http://blog.csdn.net/win_lin/article/details/13006803 | ||
| 39 | +*/ | ||
| 40 | +class SrsComplexHandshake | ||
| 41 | +{ | ||
| 42 | +public: | ||
| 43 | + SrsComplexHandshake(); | ||
| 44 | + virtual ~SrsComplexHandshake(); | ||
| 45 | +public: | ||
| 46 | + /** | ||
| 47 | + * complex hanshake. | ||
| 48 | + * @c1, size of c1 must be 1536. | ||
| 49 | + * @remark, user must free the c1. | ||
| 50 | + * @return user must: | ||
| 51 | + * continue connect app if success, | ||
| 52 | + * try simple handshake if error is ERROR_RTMP_TRY_SIMPLE_HS, | ||
| 53 | + * otherwise, disconnect | ||
| 54 | + */ | ||
| 55 | + virtual int handshake(SrsSocket& skt, char* c1); | ||
| 56 | +}; | ||
| 57 | + | ||
| 58 | +#endif |
| @@ -62,6 +62,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -62,6 +62,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 62 | #define ERROR_RTMP_MESSAGE_ENCODE 308 | 62 | #define ERROR_RTMP_MESSAGE_ENCODE 308 |
| 63 | #define ERROR_RTMP_AMF0_ENCODE 309 | 63 | #define ERROR_RTMP_AMF0_ENCODE 309 |
| 64 | #define ERROR_RTMP_CHUNK_SIZE 310 | 64 | #define ERROR_RTMP_CHUNK_SIZE 310 |
| 65 | +#define ERROR_RTMP_TRY_SIMPLE_HS 311 | ||
| 65 | 66 | ||
| 66 | #define ERROR_SYSTEM_STREAM_INIT 400 | 67 | #define ERROR_SYSTEM_STREAM_INIT 400 |
| 67 | #define ERROR_SYSTEM_PACKET_INVALID 401 | 68 | #define ERROR_SYSTEM_PACKET_INVALID 401 |
| @@ -29,6 +29,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -29,6 +29,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 29 | #include <srs_core_protocol.hpp> | 29 | #include <srs_core_protocol.hpp> |
| 30 | #include <srs_core_auto_free.hpp> | 30 | #include <srs_core_auto_free.hpp> |
| 31 | #include <srs_core_amf0.hpp> | 31 | #include <srs_core_amf0.hpp> |
| 32 | +#include <srs_core_complex_handshake.hpp> | ||
| 32 | 33 | ||
| 33 | /** | 34 | /** |
| 34 | * the signature for packets to client. | 35 | * the signature for packets to client. |
| @@ -139,11 +140,13 @@ SrsRtmp::SrsRtmp(st_netfd_t client_stfd) | @@ -139,11 +140,13 @@ SrsRtmp::SrsRtmp(st_netfd_t client_stfd) | ||
| 139 | { | 140 | { |
| 140 | protocol = new SrsProtocol(client_stfd); | 141 | protocol = new SrsProtocol(client_stfd); |
| 141 | stfd = client_stfd; | 142 | stfd = client_stfd; |
| 143 | + complex_handshake = new SrsComplexHandshake(); | ||
| 142 | } | 144 | } |
| 143 | 145 | ||
| 144 | SrsRtmp::~SrsRtmp() | 146 | SrsRtmp::~SrsRtmp() |
| 145 | { | 147 | { |
| 146 | srs_freep(protocol); | 148 | srs_freep(protocol); |
| 149 | + srs_freep(complex_handshake); | ||
| 147 | } | 150 | } |
| 148 | 151 | ||
| 149 | void SrsRtmp::set_recv_timeout(int timeout_ms) | 152 | void SrsRtmp::set_recv_timeout(int timeout_ms) |
| @@ -189,6 +192,18 @@ int SrsRtmp::handshake() | @@ -189,6 +192,18 @@ int SrsRtmp::handshake() | ||
| 189 | return ret; | 192 | return ret; |
| 190 | } | 193 | } |
| 191 | srs_verbose("check c0 success, required plain text."); | 194 | srs_verbose("check c0 success, required plain text."); |
| 195 | + | ||
| 196 | + // try complex handshake | ||
| 197 | + ret = complex_handshake->handshake(skt, c0c1 + 1); | ||
| 198 | + if (ret == ERROR_SUCCESS) { | ||
| 199 | + srs_trace("complex handshake success."); | ||
| 200 | + return ret; | ||
| 201 | + } | ||
| 202 | + if (ret != ERROR_RTMP_TRY_SIMPLE_HS) { | ||
| 203 | + srs_error("complex handshake failed. ret=%d", ret); | ||
| 204 | + return ret; | ||
| 205 | + } | ||
| 206 | + srs_info("complex handhskae failed, try simple. ret=%d", ret); | ||
| 192 | 207 | ||
| 193 | char* s0s1s2 = new char[3073]; | 208 | char* s0s1s2 = new char[3073]; |
| 194 | SrsAutoFree(char, s0s1s2, true); | 209 | SrsAutoFree(char, s0s1s2, true); |
| @@ -208,7 +223,7 @@ int SrsRtmp::handshake() | @@ -208,7 +223,7 @@ int SrsRtmp::handshake() | ||
| 208 | } | 223 | } |
| 209 | srs_verbose("read c2 success."); | 224 | srs_verbose("read c2 success."); |
| 210 | 225 | ||
| 211 | - srs_trace("handshake success."); | 226 | + srs_trace("simple handshake success."); |
| 212 | 227 | ||
| 213 | return ret; | 228 | return ret; |
| 214 | } | 229 | } |
| @@ -39,6 +39,7 @@ class ISrsMessage; | @@ -39,6 +39,7 @@ class ISrsMessage; | ||
| 39 | class SrsCommonMessage; | 39 | class SrsCommonMessage; |
| 40 | class SrsCreateStreamPacket; | 40 | class SrsCreateStreamPacket; |
| 41 | class SrsFMLEStartPacket; | 41 | class SrsFMLEStartPacket; |
| 42 | +class SrsComplexHandshake; | ||
| 42 | 43 | ||
| 43 | /** | 44 | /** |
| 44 | * the original request from client. | 45 | * the original request from client. |
| @@ -95,6 +96,7 @@ enum SrsClientType | @@ -95,6 +96,7 @@ enum SrsClientType | ||
| 95 | class SrsRtmp | 96 | class SrsRtmp |
| 96 | { | 97 | { |
| 97 | private: | 98 | private: |
| 99 | + SrsComplexHandshake* complex_handshake; | ||
| 98 | SrsProtocol* protocol; | 100 | SrsProtocol* protocol; |
| 99 | st_netfd_t stfd; | 101 | st_netfd_t stfd; |
| 100 | public: | 102 | public: |
| @@ -68,34 +68,10 @@ int SrsConsumer::enqueue(SrsSharedPtrMessage* msg) | @@ -68,34 +68,10 @@ int SrsConsumer::enqueue(SrsSharedPtrMessage* msg) | ||
| 68 | { | 68 | { |
| 69 | int ret = ERROR_SUCCESS; | 69 | int ret = ERROR_SUCCESS; |
| 70 | 70 | ||
| 71 | - /** | ||
| 72 | - * we use a very simple time jitter detect/correct algorithm: | ||
| 73 | - * 1. delta: ensure the delta is positive and valid, | ||
| 74 | - * we set the delta to DEFAULT_FRAME_TIME_MS, | ||
| 75 | - * if the delta of time is nagative or greater than CONST_MAX_JITTER_MS. | ||
| 76 | - * 2. last_pkt_time: specifies the original packet time, | ||
| 77 | - * is used to detect next jitter. | ||
| 78 | - * 3. last_pkt_correct_time: simply add the positive delta, | ||
| 79 | - * and enforce the time monotonically. | ||
| 80 | - */ | ||
| 81 | - int32_t time = msg->header.timestamp; | ||
| 82 | - int32_t delta = time - last_pkt_time; | ||
| 83 | - | ||
| 84 | - // if jitter detected, reset the delta. | ||
| 85 | - if (delta < 0 || delta > CONST_MAX_JITTER_MS) { | ||
| 86 | - delta = DEFAULT_FRAME_TIME_MS; | ||
| 87 | - | ||
| 88 | - srs_info("jitter detected, delta=%d, last_pkt=%d, time=%d, correct_to=%d", | ||
| 89 | - delta, last_pkt_time, time, last_pkt_correct_time + delta); | ||
| 90 | - } else { | ||
| 91 | - srs_verbose("timestamp no jitter. time=%d, last_pkt=%d, correct_to=%d", | ||
| 92 | - time, last_pkt_time, last_pkt_correct_time + delta); | 71 | + if ((ret = jitter_correct(msg)) != ERROR_SUCCESS) { |
| 72 | + return ret; | ||
| 93 | } | 73 | } |
| 94 | 74 | ||
| 95 | - last_pkt_correct_time = srs_max(0, last_pkt_correct_time + delta); | ||
| 96 | - msg->header.timestamp = last_pkt_correct_time; | ||
| 97 | - last_pkt_time = time; | ||
| 98 | - | ||
| 99 | msgs.push_back(msg); | 75 | msgs.push_back(msg); |
| 100 | 76 | ||
| 101 | return ret; | 77 | return ret; |
| @@ -130,6 +106,41 @@ int SrsConsumer::get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& c | @@ -130,6 +106,41 @@ int SrsConsumer::get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& c | ||
| 130 | return ret; | 106 | return ret; |
| 131 | } | 107 | } |
| 132 | 108 | ||
| 109 | +int SrsConsumer::jitter_correct(SrsSharedPtrMessage* msg) | ||
| 110 | +{ | ||
| 111 | + int ret = ERROR_SUCCESS; | ||
| 112 | + | ||
| 113 | + /** | ||
| 114 | + * we use a very simple time jitter detect/correct algorithm: | ||
| 115 | + * 1. delta: ensure the delta is positive and valid, | ||
| 116 | + * we set the delta to DEFAULT_FRAME_TIME_MS, | ||
| 117 | + * if the delta of time is nagative or greater than CONST_MAX_JITTER_MS. | ||
| 118 | + * 2. last_pkt_time: specifies the original packet time, | ||
| 119 | + * is used to detect next jitter. | ||
| 120 | + * 3. last_pkt_correct_time: simply add the positive delta, | ||
| 121 | + * and enforce the time monotonically. | ||
| 122 | + */ | ||
| 123 | + int32_t time = msg->header.timestamp; | ||
| 124 | + int32_t delta = time - last_pkt_time; | ||
| 125 | + | ||
| 126 | + // if jitter detected, reset the delta. | ||
| 127 | + if (delta < 0 || delta > CONST_MAX_JITTER_MS) { | ||
| 128 | + delta = DEFAULT_FRAME_TIME_MS; | ||
| 129 | + | ||
| 130 | + srs_info("jitter detected, delta=%d, last_pkt=%d, time=%d, correct_to=%d", | ||
| 131 | + delta, last_pkt_time, time, last_pkt_correct_time + delta); | ||
| 132 | + } else { | ||
| 133 | + srs_verbose("timestamp no jitter. time=%d, last_pkt=%d, correct_to=%d", | ||
| 134 | + time, last_pkt_time, last_pkt_correct_time + delta); | ||
| 135 | + } | ||
| 136 | + | ||
| 137 | + last_pkt_correct_time = srs_max(0, last_pkt_correct_time + delta); | ||
| 138 | + msg->header.timestamp = last_pkt_correct_time; | ||
| 139 | + last_pkt_time = time; | ||
| 140 | + | ||
| 141 | + return ret; | ||
| 142 | +} | ||
| 143 | + | ||
| 133 | SrsSource::SrsSource(std::string _stream_url) | 144 | SrsSource::SrsSource(std::string _stream_url) |
| 134 | { | 145 | { |
| 135 | stream_url = _stream_url; | 146 | stream_url = _stream_url; |
| @@ -65,6 +65,11 @@ public: | @@ -65,6 +65,11 @@ public: | ||
| 65 | * @max_count the max count to dequeue, 0 to dequeue all. | 65 | * @max_count the max count to dequeue, 0 to dequeue all. |
| 66 | */ | 66 | */ |
| 67 | virtual int get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& count); | 67 | virtual int get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& count); |
| 68 | +private: | ||
| 69 | + /** | ||
| 70 | + * detect the time jitter and correct it. | ||
| 71 | + */ | ||
| 72 | + virtual int jitter_correct(SrsSharedPtrMessage* msg); | ||
| 68 | }; | 73 | }; |
| 69 | 74 | ||
| 70 | /** | 75 | /** |
| @@ -20,6 +20,8 @@ file | @@ -20,6 +20,8 @@ file | ||
| 20 | ..\core\srs_core_codec.cpp, | 20 | ..\core\srs_core_codec.cpp, |
| 21 | ..\core\srs_core_rtmp.hpp, | 21 | ..\core\srs_core_rtmp.hpp, |
| 22 | ..\core\srs_core_rtmp.cpp, | 22 | ..\core\srs_core_rtmp.cpp, |
| 23 | + ..\core\srs_core_complex_handshake.hpp, | ||
| 24 | + ..\core\srs_core_complex_handshake.cpp, | ||
| 23 | ..\core\srs_core_protocol.hpp, | 25 | ..\core\srs_core_protocol.hpp, |
| 24 | ..\core\srs_core_protocol.cpp, | 26 | ..\core\srs_core_protocol.cpp, |
| 25 | ..\core\srs_core_amf0.hpp, | 27 | ..\core\srs_core_amf0.hpp, |
-
请 注册 或 登录 后发表评论