正在显示
9 个修改的文件
包含
188 行增加
和
124 行删除
@@ -830,6 +830,17 @@ int SrsConfig::reload_vhost(SrsConfDirective* old_root) | @@ -830,6 +830,17 @@ int SrsConfig::reload_vhost(SrsConfDirective* old_root) | ||
830 | } | 830 | } |
831 | srs_trace("vhost %s reload mr success.", vhost.c_str()); | 831 | srs_trace("vhost %s reload mr success.", vhost.c_str()); |
832 | } | 832 | } |
833 | + // chunk_size, only one per vhost. | ||
834 | + if (!srs_directive_equals(new_vhost->get("chunk_size"), old_vhost->get("chunk_size"))) { | ||
835 | + for (it = subscribes.begin(); it != subscribes.end(); ++it) { | ||
836 | + ISrsReloadHandler* subscribe = *it; | ||
837 | + if ((ret = subscribe->on_reload_vhost_chunk_size(vhost)) != ERROR_SUCCESS) { | ||
838 | + srs_error("vhost %s notify subscribes chunk_size failed. ret=%d", vhost.c_str(), ret); | ||
839 | + return ret; | ||
840 | + } | ||
841 | + } | ||
842 | + srs_trace("vhost %s reload chunk_size success.", vhost.c_str()); | ||
843 | + } | ||
833 | // mw, only one per vhost | 844 | // mw, only one per vhost |
834 | if (!srs_directive_equals(new_vhost->get("mw_latency"), old_vhost->get("mw_latency"))) { | 845 | if (!srs_directive_equals(new_vhost->get("mw_latency"), old_vhost->get("mw_latency"))) { |
835 | for (it = subscribes.begin(); it != subscribes.end(); ++it) { | 846 | for (it = subscribes.begin(); it != subscribes.end(); ++it) { |
@@ -150,6 +150,11 @@ int ISrsReloadHandler::on_reload_vhost_mw(string /*vhost*/) | @@ -150,6 +150,11 @@ int ISrsReloadHandler::on_reload_vhost_mw(string /*vhost*/) | ||
150 | return ERROR_SUCCESS; | 150 | return ERROR_SUCCESS; |
151 | } | 151 | } |
152 | 152 | ||
153 | +int ISrsReloadHandler::on_reload_vhost_chunk_size(string /*vhost*/) | ||
154 | +{ | ||
155 | + return ERROR_SUCCESS; | ||
156 | +} | ||
157 | + | ||
153 | int ISrsReloadHandler::on_reload_vhost_transcode(string /*vhost*/) | 158 | int ISrsReloadHandler::on_reload_vhost_transcode(string /*vhost*/) |
154 | { | 159 | { |
155 | return ERROR_SUCCESS; | 160 | return ERROR_SUCCESS; |
@@ -67,6 +67,7 @@ public: | @@ -67,6 +67,7 @@ public: | ||
67 | virtual int on_reload_vhost_dvr(std::string vhost); | 67 | virtual int on_reload_vhost_dvr(std::string vhost); |
68 | virtual int on_reload_vhost_mr(std::string vhost); | 68 | virtual int on_reload_vhost_mr(std::string vhost); |
69 | virtual int on_reload_vhost_mw(std::string vhost); | 69 | virtual int on_reload_vhost_mw(std::string vhost); |
70 | + virtual int on_reload_vhost_chunk_size(std::string vhost); | ||
70 | virtual int on_reload_vhost_transcode(std::string vhost); | 71 | virtual int on_reload_vhost_transcode(std::string vhost); |
71 | virtual int on_reload_ingest_removed(std::string vhost, std::string ingest_id); | 72 | virtual int on_reload_ingest_removed(std::string vhost, std::string ingest_id); |
72 | virtual int on_reload_ingest_added(std::string vhost, std::string ingest_id); | 73 | virtual int on_reload_ingest_added(std::string vhost, std::string ingest_id); |
@@ -1173,7 +1173,7 @@ int SrsSource::on_audio(SrsCommonMessage* __audio) | @@ -1173,7 +1173,7 @@ int SrsSource::on_audio(SrsCommonMessage* __audio) | ||
1173 | std::vector<SrsForwarder*>::iterator it; | 1173 | std::vector<SrsForwarder*>::iterator it; |
1174 | for (it = forwarders.begin(); it != forwarders.end(); ++it) { | 1174 | for (it = forwarders.begin(); it != forwarders.end(); ++it) { |
1175 | SrsForwarder* forwarder = *it; | 1175 | SrsForwarder* forwarder = *it; |
1176 | - if ((ret = forwarder->on_audio(msg.copy())) != ERROR_SUCCESS) { | 1176 | + if ((ret = forwarder->on_audio(&msg)) != ERROR_SUCCESS) { |
1177 | srs_error("forwarder process audio message failed. ret=%d", ret); | 1177 | srs_error("forwarder process audio message failed. ret=%d", ret); |
1178 | return ret; | 1178 | return ret; |
1179 | } | 1179 | } |
@@ -162,6 +162,8 @@ void check_macro_features() | @@ -162,6 +162,8 @@ void check_macro_features() | ||
162 | srs_warn("MR(merged-read) is disabled, hurts read performance. @see %s", RTMP_SIG_SRS_ISSUES(241)); | 162 | srs_warn("MR(merged-read) is disabled, hurts read performance. @see %s", RTMP_SIG_SRS_ISSUES(241)); |
163 | #endif | 163 | #endif |
164 | 164 | ||
165 | + srs_trace("writev limits write %d iovs a time", sysconf(_SC_IOV_MAX)); | ||
166 | + | ||
165 | #if VERSION_MAJOR > 1 | 167 | #if VERSION_MAJOR > 1 |
166 | #warning "using develop SRS, please use release instead." | 168 | #warning "using develop SRS, please use release instead." |
167 | srs_warn("SRS %s is develop branch, please use %s instead", RTMP_SIG_SRS_VERSION, RTMP_SIG_SRS_RELEASE); | 169 | srs_warn("SRS %s is develop branch, please use %s instead", RTMP_SIG_SRS_VERSION, RTMP_SIG_SRS_RELEASE); |
@@ -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_autofree.hpp> | 29 | #include <srs_core_autofree.hpp> |
30 | #include <srs_kernel_utility.hpp> | 30 | #include <srs_kernel_utility.hpp> |
31 | #include <srs_protocol_buffer.hpp> | 31 | #include <srs_protocol_buffer.hpp> |
32 | +#include <srs_protocol_utility.hpp> | ||
32 | 33 | ||
33 | #include <stdlib.h> | 34 | #include <stdlib.h> |
34 | using namespace std; | 35 | using namespace std; |
@@ -167,22 +168,6 @@ messages. | @@ -167,22 +168,6 @@ messages. | ||
167 | ***************************************************************************** | 168 | ***************************************************************************** |
168 | ****************************************************************************/ | 169 | ****************************************************************************/ |
169 | /** | 170 | /** |
170 | -* 6.1. Chunk Format | ||
171 | -* Extended timestamp: 0 or 4 bytes | ||
172 | -* This field MUST be sent when the normal timsestamp is set to | ||
173 | -* 0xffffff, it MUST NOT be sent if the normal timestamp is set to | ||
174 | -* anything else. So for values less than 0xffffff the normal | ||
175 | -* timestamp field SHOULD be used in which case the extended timestamp | ||
176 | -* MUST NOT be present. For values greater than or equal to 0xffffff | ||
177 | -* the normal timestamp field MUST NOT be used and MUST be set to | ||
178 | -* 0xffffff and the extended timestamp MUST be sent. | ||
179 | -*/ | ||
180 | -#define RTMP_EXTENDED_TIMESTAMP 0xFFFFFF | ||
181 | - | ||
182 | -/**************************************************************************** | ||
183 | -***************************************************************************** | ||
184 | -****************************************************************************/ | ||
185 | -/** | ||
186 | * amf0 command message, command name macros | 171 | * amf0 command message, command name macros |
187 | */ | 172 | */ |
188 | #define RTMP_AMF0_COMMAND_CONNECT "connect" | 173 | #define RTMP_AMF0_COMMAND_CONNECT "connect" |
@@ -756,13 +741,11 @@ int SrsProtocol::do_send_messages(SrsSharedPtrMessage** msgs, int nb_msgs) | @@ -756,13 +741,11 @@ int SrsProtocol::do_send_messages(SrsSharedPtrMessage** msgs, int nb_msgs) | ||
756 | // always write the header event payload is empty. | 741 | // always write the header event payload is empty. |
757 | while (p < pend) { | 742 | while (p < pend) { |
758 | // always has header | 743 | // always has header |
759 | - int nbh = 0; | ||
760 | - char* header = NULL; | ||
761 | - generate_chunk_header(c0c3_cache, &msg->header, p == msg->payload, &nbh, &header); | 744 | + int nbh = srs_chunk_header(c0c3_cache, &msg->header, p == msg->payload); |
762 | srs_assert(nbh > 0); | 745 | srs_assert(nbh > 0); |
763 | 746 | ||
764 | // header iov | 747 | // header iov |
765 | - iov[0].iov_base = header; | 748 | + iov[0].iov_base = c0c3_cache; |
766 | iov[0].iov_len = nbh; | 749 | iov[0].iov_len = nbh; |
767 | 750 | ||
768 | // payload iov | 751 | // payload iov |
@@ -813,7 +796,7 @@ int SrsProtocol::do_send_messages(SrsSharedPtrMessage** msgs, int nb_msgs) | @@ -813,7 +796,7 @@ int SrsProtocol::do_send_messages(SrsSharedPtrMessage** msgs, int nb_msgs) | ||
813 | // sendout all messages and reset the cache, then send again. | 796 | // sendout all messages and reset the cache, then send again. |
814 | if ((ret = skt->writev(out_iovs, iov_index, NULL)) != ERROR_SUCCESS) { | 797 | if ((ret = skt->writev(out_iovs, iov_index, NULL)) != ERROR_SUCCESS) { |
815 | if (!srs_is_client_gracefully_close(ret)) { | 798 | if (!srs_is_client_gracefully_close(ret)) { |
816 | - srs_error("send with writev failed. ret=%d", ret); | 799 | + srs_error("send msgs with writev failed. ret=%d", ret); |
817 | } | 800 | } |
818 | return ret; | 801 | return ret; |
819 | } | 802 | } |
@@ -834,31 +817,47 @@ int SrsProtocol::do_send_messages(SrsSharedPtrMessage** msgs, int nb_msgs) | @@ -834,31 +817,47 @@ int SrsProtocol::do_send_messages(SrsSharedPtrMessage** msgs, int nb_msgs) | ||
834 | if (iov_index <= 0) { | 817 | if (iov_index <= 0) { |
835 | return ret; | 818 | return ret; |
836 | } | 819 | } |
837 | - | ||
838 | - // calc the bytes of iovs, for debug. | ||
839 | #if 0 | 820 | #if 0 |
821 | + // calc the bytes of iovs, for debug. | ||
840 | int nb_bytes = 0; | 822 | int nb_bytes = 0; |
841 | for (int i = 0; i < iov_index; i++) { | 823 | for (int i = 0; i < iov_index; i++) { |
842 | iovec* iov = out_iovs + i; | 824 | iovec* iov = out_iovs + i; |
843 | nb_bytes += iov->iov_len; | 825 | nb_bytes += iov->iov_len; |
844 | } | 826 | } |
845 | - srs_warn("mw %d msgs %dB in %d iovs, max_msgs=%d, nb_out_iovs=%d", | 827 | + srs_info("mw %d msgs %dB in %d iovs, max_msgs=%d, nb_out_iovs=%d", |
846 | nb_msgs, nb_bytes, iov_index, SRS_PERF_MW_MSGS, nb_out_iovs); | 828 | nb_msgs, nb_bytes, iov_index, SRS_PERF_MW_MSGS, nb_out_iovs); |
847 | #else | 829 | #else |
848 | srs_info("mw %d msgs in %d iovs, max_msgs=%d, nb_out_iovs=%d", | 830 | srs_info("mw %d msgs in %d iovs, max_msgs=%d, nb_out_iovs=%d", |
849 | nb_msgs, iov_index, SRS_PERF_MW_MSGS, nb_out_iovs); | 831 | nb_msgs, iov_index, SRS_PERF_MW_MSGS, nb_out_iovs); |
850 | #endif | 832 | #endif |
851 | 833 | ||
852 | - // send by writev | ||
853 | - // sendout header and payload by writev. | ||
854 | - // decrease the sys invoke count to get higher performance. | ||
855 | - if ((ret = skt->writev(out_iovs, iov_index, NULL)) != ERROR_SUCCESS) { | ||
856 | - if (!srs_is_client_gracefully_close(ret)) { | ||
857 | - srs_error("send with writev failed. ret=%d", ret); | 834 | + // the limits of writev iovs. |
835 | + static int limits = sysconf(_SC_IOV_MAX); | ||
836 | + | ||
837 | + // send in a time. | ||
838 | + if (iov_index < limits) { | ||
839 | + if ((ret = skt->writev(out_iovs, iov_index, NULL)) != ERROR_SUCCESS) { | ||
840 | + if (!srs_is_client_gracefully_close(ret)) { | ||
841 | + srs_error("send with writev failed. ret=%d", ret); | ||
842 | + } | ||
843 | + return ret; | ||
858 | } | 844 | } |
859 | return ret; | 845 | return ret; |
860 | } | 846 | } |
861 | 847 | ||
848 | + // send in multiple times. | ||
849 | + int cur_iov = 0; | ||
850 | + while (cur_iov < iov_index) { | ||
851 | + int cur_count = srs_min(limits, iov_index - cur_iov); | ||
852 | + if ((ret = skt->writev(out_iovs + cur_iov, cur_count, NULL)) != ERROR_SUCCESS) { | ||
853 | + if (!srs_is_client_gracefully_close(ret)) { | ||
854 | + srs_error("send with writev failed. ret=%d", ret); | ||
855 | + } | ||
856 | + return ret; | ||
857 | + } | ||
858 | + cur_iov += cur_count; | ||
859 | + } | ||
860 | + | ||
862 | return ret; | 861 | return ret; |
863 | } | 862 | } |
864 | 863 | ||
@@ -888,102 +887,46 @@ int SrsProtocol::do_send_and_free_packet(SrsPacket* packet, int stream_id) | @@ -888,102 +887,46 @@ int SrsProtocol::do_send_and_free_packet(SrsPacket* packet, int stream_id) | ||
888 | header.message_type = packet->get_message_type(); | 887 | header.message_type = packet->get_message_type(); |
889 | header.stream_id = stream_id; | 888 | header.stream_id = stream_id; |
890 | header.perfer_cid = packet->get_prefer_cid(); | 889 | header.perfer_cid = packet->get_prefer_cid(); |
891 | - | ||
892 | - SrsSharedPtrMessage* msg = new SrsSharedPtrMessage(); | ||
893 | - ret = msg->create(&header, payload, size); | 890 | + |
891 | + ret = do_simple_send(&header, payload, size); | ||
894 | if (ret == ERROR_SUCCESS) { | 892 | if (ret == ERROR_SUCCESS) { |
895 | - ret = do_send_messages(&msg, 1); | ||
896 | - if (ret == ERROR_SUCCESS) { | ||
897 | - ret = on_send_packet(msg, packet); | ||
898 | - } | 893 | + ret = on_send_packet(&header, packet); |
899 | } | 894 | } |
900 | - | ||
901 | - // donot use the auto free to free the msg, | ||
902 | - // for performance issue. | ||
903 | - srs_freep(msg); | ||
904 | 895 | ||
905 | return ret; | 896 | return ret; |
906 | } | 897 | } |
907 | 898 | ||
908 | -void SrsProtocol::generate_chunk_header(char* cache, SrsMessageHeader* mh, bool c0, int* pnbh, char** ph) | 899 | +int SrsProtocol::do_simple_send(SrsMessageHeader* mh, char* payload, int size) |
909 | { | 900 | { |
910 | - // to directly set the field. | ||
911 | - char* pp = NULL; | ||
912 | - | ||
913 | - // generate the header. | ||
914 | - char* p = cache; | ||
915 | - | ||
916 | - // timestamp for c0/c3 | ||
917 | - u_int32_t timestamp = (u_int32_t)mh->timestamp; | 901 | + int ret = ERROR_SUCCESS; |
918 | 902 | ||
919 | - if (c0) { | ||
920 | - // write new chunk stream header, fmt is 0 | ||
921 | - *p++ = 0x00 | (mh->perfer_cid & 0x3F); | ||
922 | - | ||
923 | - // chunk message header, 11 bytes | ||
924 | - // timestamp, 3bytes, big-endian | ||
925 | - if (timestamp < RTMP_EXTENDED_TIMESTAMP) { | ||
926 | - pp = (char*)×tamp; | ||
927 | - *p++ = pp[2]; | ||
928 | - *p++ = pp[1]; | ||
929 | - *p++ = pp[0]; | ||
930 | - } else { | ||
931 | - *p++ = 0xFF; | ||
932 | - *p++ = 0xFF; | ||
933 | - *p++ = 0xFF; | ||
934 | - } | 903 | + // we directly send out the packet, |
904 | + // use very simple algorithm, not very fast, | ||
905 | + // but it's ok. | ||
906 | + char* p = payload; | ||
907 | + char* end = p + size; | ||
908 | + char c0c3[SRS_CONSTS_RTMP_MAX_FMT0_HEADER_SIZE]; | ||
909 | + while (p < end) { | ||
910 | + int nbh = srs_chunk_header(c0c3, mh, p == payload); | ||
935 | 911 | ||
936 | - // message_length, 3bytes, big-endian | ||
937 | - pp = (char*)&mh->payload_length; | ||
938 | - *p++ = pp[2]; | ||
939 | - *p++ = pp[1]; | ||
940 | - *p++ = pp[0]; | 912 | + iovec iovs[2]; |
913 | + iovs[0].iov_base = c0c3; | ||
914 | + iovs[0].iov_len = nbh; | ||
941 | 915 | ||
942 | - // message_type, 1bytes | ||
943 | - *p++ = mh->message_type; | 916 | + int payload_size = srs_min(end - p, out_chunk_size); |
917 | + iovs[1].iov_base = p; | ||
918 | + iovs[1].iov_len = payload_size; | ||
919 | + p += payload_size; | ||
944 | 920 | ||
945 | - // message_length, 3bytes, little-endian | ||
946 | - pp = (char*)&mh->stream_id; | ||
947 | - *p++ = pp[0]; | ||
948 | - *p++ = pp[1]; | ||
949 | - *p++ = pp[2]; | ||
950 | - *p++ = pp[3]; | ||
951 | - } else { | ||
952 | - // write no message header chunk stream, fmt is 3 | ||
953 | - // @remark, if perfer_cid > 0x3F, that is, use 2B/3B chunk header, | ||
954 | - // SRS will rollback to 1B chunk header. | ||
955 | - *p++ = 0xC0 | (mh->perfer_cid & 0x3F); | 921 | + if ((ret = skt->writev(iovs, 2, NULL)) != ERROR_SUCCESS) { |
922 | + if (!srs_is_client_gracefully_close(ret)) { | ||
923 | + srs_error("send packet with writev failed. ret=%d", ret); | ||
924 | + } | ||
925 | + return ret; | ||
926 | + } | ||
956 | } | 927 | } |
957 | 928 | ||
958 | - // for c0 | ||
959 | - // chunk extended timestamp header, 0 or 4 bytes, big-endian | ||
960 | - // | ||
961 | - // for c3: | ||
962 | - // chunk extended timestamp header, 0 or 4 bytes, big-endian | ||
963 | - // 6.1.3. Extended Timestamp | ||
964 | - // This field is transmitted only when the normal time stamp in the | ||
965 | - // chunk message header is set to 0x00ffffff. If normal time stamp is | ||
966 | - // set to any value less than 0x00ffffff, this field MUST NOT be | ||
967 | - // present. This field MUST NOT be present if the timestamp field is not | ||
968 | - // present. Type 3 chunks MUST NOT have this field. | ||
969 | - // adobe changed for Type3 chunk: | ||
970 | - // FMLE always sendout the extended-timestamp, | ||
971 | - // must send the extended-timestamp to FMS, | ||
972 | - // must send the extended-timestamp to flash-player. | ||
973 | - // @see: ngx_rtmp_prepare_message | ||
974 | - // @see: http://blog.csdn.net/win_lin/article/details/13363699 | ||
975 | - // TODO: FIXME: extract to outer. | ||
976 | - if (timestamp >= RTMP_EXTENDED_TIMESTAMP) { | ||
977 | - pp = (char*)×tamp; | ||
978 | - *p++ = pp[3]; | ||
979 | - *p++ = pp[2]; | ||
980 | - *p++ = pp[1]; | ||
981 | - *p++ = pp[0]; | ||
982 | - } | ||
983 | - | ||
984 | - // always has header | ||
985 | - *pnbh = p - cache; | ||
986 | - *ph = cache; | 929 | + return ret; |
987 | } | 930 | } |
988 | 931 | ||
989 | int SrsProtocol::do_decode_message(SrsMessageHeader& header, SrsStream* stream, SrsPacket** ppacket) | 932 | int SrsProtocol::do_decode_message(SrsMessageHeader& header, SrsStream* stream, SrsPacket** ppacket) |
@@ -1842,7 +1785,7 @@ int SrsProtocol::on_recv_message(SrsCommonMessage* msg) | @@ -1842,7 +1785,7 @@ int SrsProtocol::on_recv_message(SrsCommonMessage* msg) | ||
1842 | return ret; | 1785 | return ret; |
1843 | } | 1786 | } |
1844 | 1787 | ||
1845 | -int SrsProtocol::on_send_packet(SrsSharedPtrMessage* msg, SrsPacket* packet) | 1788 | +int SrsProtocol::on_send_packet(SrsMessageHeader* mh, SrsPacket* packet) |
1846 | { | 1789 | { |
1847 | int ret = ERROR_SUCCESS; | 1790 | int ret = ERROR_SUCCESS; |
1848 | 1791 | ||
@@ -1851,7 +1794,7 @@ int SrsProtocol::on_send_packet(SrsSharedPtrMessage* msg, SrsPacket* packet) | @@ -1851,7 +1794,7 @@ int SrsProtocol::on_send_packet(SrsSharedPtrMessage* msg, SrsPacket* packet) | ||
1851 | return ret; | 1794 | return ret; |
1852 | } | 1795 | } |
1853 | 1796 | ||
1854 | - switch (msg->header.message_type) { | 1797 | + switch (mh->message_type) { |
1855 | case RTMP_MSG_SetChunkSize: { | 1798 | case RTMP_MSG_SetChunkSize: { |
1856 | SrsSetChunkSizePacket* pkt = dynamic_cast<SrsSetChunkSizePacket*>(packet); | 1799 | SrsSetChunkSizePacket* pkt = dynamic_cast<SrsSetChunkSizePacket*>(packet); |
1857 | srs_assert(pkt != NULL); | 1800 | srs_assert(pkt != NULL); |
@@ -56,6 +56,22 @@ class SrsChunkStream; | @@ -56,6 +56,22 @@ class SrsChunkStream; | ||
56 | class SrsSharedPtrMessage; | 56 | class SrsSharedPtrMessage; |
57 | class IMergeReadHandler; | 57 | class IMergeReadHandler; |
58 | 58 | ||
59 | +/**************************************************************************** | ||
60 | +***************************************************************************** | ||
61 | +****************************************************************************/ | ||
62 | +/** | ||
63 | +* 6.1. Chunk Format | ||
64 | +* Extended timestamp: 0 or 4 bytes | ||
65 | +* This field MUST be sent when the normal timsestamp is set to | ||
66 | +* 0xffffff, it MUST NOT be sent if the normal timestamp is set to | ||
67 | +* anything else. So for values less than 0xffffff the normal | ||
68 | +* timestamp field SHOULD be used in which case the extended timestamp | ||
69 | +* MUST NOT be present. For values greater than or equal to 0xffffff | ||
70 | +* the normal timestamp field MUST NOT be used and MUST be set to | ||
71 | +* 0xffffff and the extended timestamp MUST be sent. | ||
72 | +*/ | ||
73 | +#define RTMP_EXTENDED_TIMESTAMP 0xFFFFFF | ||
74 | + | ||
59 | /** | 75 | /** |
60 | * 4.1. Message Header | 76 | * 4.1. Message Header |
61 | */ | 77 | */ |
@@ -493,14 +509,10 @@ private: | @@ -493,14 +509,10 @@ private: | ||
493 | */ | 509 | */ |
494 | virtual int do_send_and_free_packet(SrsPacket* packet, int stream_id); | 510 | virtual int do_send_and_free_packet(SrsPacket* packet, int stream_id); |
495 | /** | 511 | /** |
496 | - * generate the chunk header for msg. | ||
497 | - * @param mh, the header of msg to send. | ||
498 | - * @param c0, whether the first chunk, the c0 chunk. | ||
499 | - * @param pnbh, output the size of header. | ||
500 | - * @param ph, output the header cache. | ||
501 | - * user should never free it, it's cached header. | 512 | + * use simple algorithm to send the header and bytes. |
513 | + * @remark, for do_send_and_free_packet to send. | ||
502 | */ | 514 | */ |
503 | - virtual void generate_chunk_header(char* cache, SrsMessageHeader* mh, bool c0, int* pnbh, char** ph); | 515 | + virtual int do_simple_send(SrsMessageHeader* mh, char* payload, int size); |
504 | /** | 516 | /** |
505 | * imp for decode_message | 517 | * imp for decode_message |
506 | */ | 518 | */ |
@@ -534,7 +546,7 @@ private: | @@ -534,7 +546,7 @@ private: | ||
534 | /** | 546 | /** |
535 | * when message sentout, update the context. | 547 | * when message sentout, update the context. |
536 | */ | 548 | */ |
537 | - virtual int on_send_packet(SrsSharedPtrMessage* msg, SrsPacket* packet); | 549 | + virtual int on_send_packet(SrsMessageHeader* mh, SrsPacket* packet); |
538 | private: | 550 | private: |
539 | /** | 551 | /** |
540 | * auto response the ack message. | 552 | * auto response the ack message. |
@@ -29,6 +29,7 @@ using namespace std; | @@ -29,6 +29,7 @@ using namespace std; | ||
29 | #include <srs_kernel_log.hpp> | 29 | #include <srs_kernel_log.hpp> |
30 | #include <srs_kernel_utility.hpp> | 30 | #include <srs_kernel_utility.hpp> |
31 | #include <srs_kernel_stream.hpp> | 31 | #include <srs_kernel_stream.hpp> |
32 | +#include <srs_protocol_stack.hpp> | ||
32 | 33 | ||
33 | void srs_discovery_tc_url( | 34 | void srs_discovery_tc_url( |
34 | string tcUrl, | 35 | string tcUrl, |
@@ -203,3 +204,83 @@ bool srs_aac_startswith_adts(SrsStream* stream) | @@ -203,3 +204,83 @@ bool srs_aac_startswith_adts(SrsStream* stream) | ||
203 | return true; | 204 | return true; |
204 | } | 205 | } |
205 | 206 | ||
207 | +int srs_chunk_header(char* cache, SrsMessageHeader* mh, bool c0) | ||
208 | +{ | ||
209 | + // to directly set the field. | ||
210 | + char* pp = NULL; | ||
211 | + | ||
212 | + // generate the header. | ||
213 | + char* p = cache; | ||
214 | + | ||
215 | + // timestamp for c0/c3 | ||
216 | + u_int32_t timestamp = (u_int32_t)mh->timestamp; | ||
217 | + | ||
218 | + if (c0) { | ||
219 | + // write new chunk stream header, fmt is 0 | ||
220 | + *p++ = 0x00 | (mh->perfer_cid & 0x3F); | ||
221 | + | ||
222 | + // chunk message header, 11 bytes | ||
223 | + // timestamp, 3bytes, big-endian | ||
224 | + if (timestamp < RTMP_EXTENDED_TIMESTAMP) { | ||
225 | + pp = (char*)×tamp; | ||
226 | + *p++ = pp[2]; | ||
227 | + *p++ = pp[1]; | ||
228 | + *p++ = pp[0]; | ||
229 | + } else { | ||
230 | + *p++ = 0xFF; | ||
231 | + *p++ = 0xFF; | ||
232 | + *p++ = 0xFF; | ||
233 | + } | ||
234 | + | ||
235 | + // message_length, 3bytes, big-endian | ||
236 | + pp = (char*)&mh->payload_length; | ||
237 | + *p++ = pp[2]; | ||
238 | + *p++ = pp[1]; | ||
239 | + *p++ = pp[0]; | ||
240 | + | ||
241 | + // message_type, 1bytes | ||
242 | + *p++ = mh->message_type; | ||
243 | + | ||
244 | + // stream_id, 4bytes, little-endian | ||
245 | + pp = (char*)&mh->stream_id; | ||
246 | + *p++ = pp[0]; | ||
247 | + *p++ = pp[1]; | ||
248 | + *p++ = pp[2]; | ||
249 | + *p++ = pp[3]; | ||
250 | + } else { | ||
251 | + // write no message header chunk stream, fmt is 3 | ||
252 | + // @remark, if perfer_cid > 0x3F, that is, use 2B/3B chunk header, | ||
253 | + // SRS will rollback to 1B chunk header. | ||
254 | + *p++ = 0xC0 | (mh->perfer_cid & 0x3F); | ||
255 | + } | ||
256 | + | ||
257 | + // for c0 | ||
258 | + // chunk extended timestamp header, 0 or 4 bytes, big-endian | ||
259 | + // | ||
260 | + // for c3: | ||
261 | + // chunk extended timestamp header, 0 or 4 bytes, big-endian | ||
262 | + // 6.1.3. Extended Timestamp | ||
263 | + // This field is transmitted only when the normal time stamp in the | ||
264 | + // chunk message header is set to 0x00ffffff. If normal time stamp is | ||
265 | + // set to any value less than 0x00ffffff, this field MUST NOT be | ||
266 | + // present. This field MUST NOT be present if the timestamp field is not | ||
267 | + // present. Type 3 chunks MUST NOT have this field. | ||
268 | + // adobe changed for Type3 chunk: | ||
269 | + // FMLE always sendout the extended-timestamp, | ||
270 | + // must send the extended-timestamp to FMS, | ||
271 | + // must send the extended-timestamp to flash-player. | ||
272 | + // @see: ngx_rtmp_prepare_message | ||
273 | + // @see: http://blog.csdn.net/win_lin/article/details/13363699 | ||
274 | + // TODO: FIXME: extract to outer. | ||
275 | + if (timestamp >= RTMP_EXTENDED_TIMESTAMP) { | ||
276 | + pp = (char*)×tamp; | ||
277 | + *p++ = pp[3]; | ||
278 | + *p++ = pp[2]; | ||
279 | + *p++ = pp[1]; | ||
280 | + *p++ = pp[0]; | ||
281 | + } | ||
282 | + | ||
283 | + // always has header | ||
284 | + return p - cache; | ||
285 | +} | ||
286 | + |
@@ -34,6 +34,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -34,6 +34,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
34 | #include <srs_kernel_consts.hpp> | 34 | #include <srs_kernel_consts.hpp> |
35 | 35 | ||
36 | class SrsStream; | 36 | class SrsStream; |
37 | +class SrsMessageHeader; | ||
37 | 38 | ||
38 | /** | 39 | /** |
39 | * parse the tcUrl, output the schema, host, vhost, app and port. | 40 | * parse the tcUrl, output the schema, host, vhost, app and port. |
@@ -103,5 +104,13 @@ extern bool srs_avc_startswith_annexb(SrsStream* stream, int* pnb_start_code = N | @@ -103,5 +104,13 @@ extern bool srs_avc_startswith_annexb(SrsStream* stream, int* pnb_start_code = N | ||
103 | */ | 104 | */ |
104 | extern bool srs_aac_startswith_adts(SrsStream* stream); | 105 | extern bool srs_aac_startswith_adts(SrsStream* stream); |
105 | 106 | ||
107 | +/** | ||
108 | +* generate the chunk header for msg. | ||
109 | +* @param mh, the header of msg to send. | ||
110 | +* @param c0, whether the first chunk, the c0 chunk. | ||
111 | +* @return the size of header. | ||
112 | +*/ | ||
113 | +extern int srs_chunk_header(char* cache, SrsMessageHeader* mh, bool c0); | ||
114 | + | ||
106 | #endif | 115 | #endif |
107 | 116 |
-
请 注册 或 登录 后发表评论