winlin

add rtmp complex handshake classes

@@ -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,