正在显示
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 |
-
请 注册 或 登录 后发表评论