From bbd7ee08d458e3a247ce1d80d3ad8c1705f53d37 Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 24 May 2021 15:19:49 +0800 Subject: [PATCH 1/3] Update README.md --- README.md | 49 +++++++++++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 9b5514fa0..96d7b1921 100755 --- a/README.md +++ b/README.md @@ -9,47 +9,42 @@ SRS/4.0,[Leo][release4],是一个简单高效的实时视频服务器,支 SRS is a simple, high efficiency and realtime video server, supports RTMP/WebRTC/HLS/HTTP-FLV/SRT/GB28181. -> Remark: Although SRS is licenced under [MIT][LICENSE], but there are some depended libraries which are distributed using their own licenses, please read [License Mixing][LicenseMixing]. +> Note: SRS is licenced under [MIT][LICENSE], but some depended libraries are distributed using their [own licenses][LicenseMixing]. ## Usage -Recommend running SRS by [docker][docker-srs4], images is [here](https://hub.docker.com/r/ossrs/srs/tags) or [there](https://cr.console.aliyun.com/repository/cn-hangzhou/ossrs/srs/images): +Run SRS by [docker][docker-srs4], images is [here](https://hub.docker.com/r/ossrs/srs/tags) or [there](https://cr.console.aliyun.com/repository/cn-hangzhou/ossrs/srs/images), +please set the CANDIDATE ([CN][v4_CN_WebRTC#config-candidate],[EN][v4_EN_WebRTC#config-candidate]) if WebRTC enabled: ```bash -docker run --rm -p 1935:1935 -p 1985:1985 -p 8080:8080 \ +docker run --rm -it -p 1935:1935 -p 1985:1985 -p 8080:8080 \ --env CANDIDATE=$(ifconfig en0 inet| grep 'inet '|awk '{print $2}') -p 8000:8000/udp \ - ossrs/srs:v4.0.85 + ossrs/srs:v4.0.117 ./objs/srs -c conf/srs.conf ``` -> To enable WebRTC, user MUST set the env `CANDIDATE`, see [wiki](https://github.com/ossrs/srs/wiki/v4_CN_WebRTC#config-candidate). - -Open [http://localhost:8080/](http://localhost:8080/) to check it, then publish -[stream](https://github.com/ossrs/srs/blob/3.0release/trunk/doc/source.flv) by: - -```bash -docker run --rm --network=host ossrs/srs:encoder ffmpeg -re -i ./doc/source.flv \ - -c copy -f flv -y rtmp://localhost/live/livestream -``` -> Note: If WebRTC enabled, you can publish by [H5](http://localhost:8080/players/rtc_publisher.html?autostart=true). - -Play the following streams by [players](https://ossrs.net): - -* VLC(RTMP): rtmp://localhost/live/livestream -* H5(HTTP-FLV): [http://localhost:8080/live/livestream.flv](http://localhost:8080/players/srs_player.html?autostart=true&stream=livestream.flv&port=8080&schema=http) -* H5(HLS): [http://localhost:8080/live/livestream.m3u8](http://localhost:8080/players/srs_player.html?autostart=true&stream=livestream.m3u8&port=8080&schema=http) -* H5(WebRTC): [webrtc://localhost/live/livestream](http://localhost:8080/players/rtc_player.html?autostart=true) - -It's also very easy to build from source: +Or build SRS from source(or [mirrors](#mirrors)), by CentOS7(or Linux([CN][v4_CN_Build],[EN][v4_EN_Build])): ``` -git clone -b develop https://gitee.com/ossrs/srs.git srs && +git clone -b develop https://gitee.com/ossrs/srs.git && cd srs/trunk && ./configure && make && ./objs/srs -c conf/srs.conf ``` -> Note: We use [mirrors(gitee)](#mirrors) here, but it's also ok to `git clone https://github.com/ossrs/srs.git` +Open [http://localhost:8080/](http://localhost:8080/) to check it, then publish +[stream](https://github.com/ossrs/srs/blob/3.0release/trunk/doc/source.flv) by FFmpeg. +It's also able to [publish by H5](http://localhost:8080/players/rtc_publisher.html?autostart=true) if WebRTC is enabled: -> Remark: Recommend to use Centos7 64bits, please read wiki([CN][v4_CN_Build],[EN][v4_EN_Build]), or use [docker][docker-dev]. +```bash +docker run --rm -it --network=host ossrs/srs:encoder \ + ffmpeg -re -i ./doc/source.flv -c copy -f flv -y rtmp://localhost/live/livestream +``` + +Play the following streams by [players](https://ossrs.net): + +* RTMP (by [VLC](https://www.videolan.org/)): rtmp://localhost/live/livestream +* H5(HTTP-FLV): [http://localhost:8080/live/livestream.flv](http://localhost:8080/players/srs_player.html?autostart=true&stream=livestream.flv&port=8080&schema=http) +* H5(HLS): [http://localhost:8080/live/livestream.m3u8](http://localhost:8080/players/srs_player.html?autostart=true&stream=livestream.m3u8&port=8080&schema=http) +* H5(WebRTC): [webrtc://localhost/live/livestream](http://localhost:8080/players/rtc_player.html?autostart=true) @@ -1460,6 +1455,8 @@ Winlin [v4_EN_SampleRealtime]: https://github.com/ossrs/srs/wiki/v4_EN_SampleRealtime [v4_CN_WebRTC]: https://github.com/ossrs/srs/wiki/v4_CN_WebRTC [v4_EN_WebRTC]: https://github.com/ossrs/srs/wiki/v4_EN_WebRTC +[v4_CN_WebRTC#config-candidate]: https://github.com/ossrs/srs/wiki/v4_CN_WebRTC#config-candidate +[v4_EN_WebRTC#config-candidate]: https://github.com/ossrs/srs/wiki/v4_EN_WebRTC#config-candidate [v4_CN_SampleARM]: https://github.com/ossrs/srs/wiki/v4_CN_SampleARM [v4_EN_SampleARM]: https://github.com/ossrs/srs/wiki/v4_EN_SampleARM [v4_CN_SampleIngest]: https://github.com/ossrs/srs/wiki/v4_CN_SampleIngest From 4d6f00e6bf50267c88c6ebfc6fc31304a75ccec3 Mon Sep 17 00:00:00 2001 From: cfw11 <34058899+cfw11@users.noreply.github.com> Date: Fri, 28 May 2021 21:19:05 +0800 Subject: [PATCH 2/3] GB28181: fix parse rtp-tcp failed (#2378) * fix parse rtp-tcp failed * fix parse rtp-tcp failed Co-authored-by: cfw --- .gitignore | 2 + trunk/conf/push.gb28181.conf | 7 +- trunk/src/app/srs_app_gb28181.cpp | 470 ++++-------------------------- trunk/src/app/srs_app_gb28181.hpp | 34 +-- 4 files changed, 71 insertions(+), 442 deletions(-) diff --git a/.gitignore b/.gitignore index 50715e164..f7e6541ff 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,5 @@ .idea .DS_Store +/cmake-build-debug/ +/CMakeLists.txt diff --git a/trunk/conf/push.gb28181.conf b/trunk/conf/push.gb28181.conf index c64a6dde0..0890dd94f 100644 --- a/trunk/conf/push.gb28181.conf +++ b/trunk/conf/push.gb28181.conf @@ -33,8 +33,8 @@ stream_caster { # 接收设备端rtp流的多路复用端口 listen 9000; # 多路复用端口类型,on为tcp,off为udp - # 默认:off - tcp_enable off; + # 默认:on + tcp_enable on; # rtp接收监听端口范围,最小值 rtp_port_min 58200; @@ -64,7 +64,8 @@ stream_caster { # 是否开启rtp缓冲 # 开启之后能有效解决rtp乱序等问题 - jitterbuffer_enable on; + # tcp模式建议关闭 + jitterbuffer_enable off; # 服务器主机号,可以域名或ip地址 # 也就是设备端将媒体发送的地址,如果是服务器是内外网 diff --git a/trunk/src/app/srs_app_gb28181.cpp b/trunk/src/app/srs_app_gb28181.cpp index 3fd610428..0fe9ff637 100644 --- a/trunk/src/app/srs_app_gb28181.cpp +++ b/trunk/src/app/srs_app_gb28181.cpp @@ -202,6 +202,11 @@ srs_error_t SrsGb28181PsRtpProcessor::on_udp_packet(const sockaddr* from, const return on_rtp_packet(from, fromlen, buf, nb_buf); } } +srs_error_t SrsGb28181PsRtpProcessor::on_tcp_packet(const sockaddr* from, const int fromlen, char* buf, int nb_buf) +{ + on_udp_packet(from, fromlen, buf, nb_buf); +} + srs_error_t SrsGb28181PsRtpProcessor::on_rtp_packet(const sockaddr* from, const int fromlen, char* buf, int nb_buf) { @@ -460,334 +465,6 @@ srs_error_t SrsGb28181PsRtpProcessor::on_rtp_packet_jitter(const sockaddr* from, return err; } -//SrsGb28181TcpPsRtpProcessor -SrsGb28181TcpPsRtpProcessor::SrsGb28181TcpPsRtpProcessor(SrsGb28181Config* c, std::string id) -{ - config = c; - pprint = SrsPithyPrint::create_caster(); - channel_id = id; -} - -SrsGb28181TcpPsRtpProcessor::~SrsGb28181TcpPsRtpProcessor() -{ - dispose(); - srs_freep(pprint); -} - -void SrsGb28181TcpPsRtpProcessor::dispose() -{ - map::iterator it2; - for (it2 = cache_ps_rtp_packet.begin(); it2 != cache_ps_rtp_packet.end(); ++it2) { - srs_freep(it2->second); - } - cache_ps_rtp_packet.clear(); - - clear_pre_packet(); - - return; -} - -void SrsGb28181TcpPsRtpProcessor::clear_pre_packet() -{ - map::iterator it; - for (it = pre_packet.begin(); it != pre_packet.end(); ++it) { - srs_freep(it->second); - } - pre_packet.clear(); -} - -srs_error_t SrsGb28181TcpPsRtpProcessor::on_rtp(char* buf, int nb_buf, std::string ip, int port) -{ - srs_error_t err = srs_success; - - if (config->jitterbuffer_enable) { - err = on_rtp_packet_jitter(buf, nb_buf, ip, port); - if (err != srs_success) { - srs_warn("SrsGb28181TcpPsRtpProcessor::on_rtp on_rtp_packet_jitter err"); - } - } - else { - return on_rtp_packet(buf, nb_buf, ip, port); - } - return err; -} - -srs_error_t SrsGb28181TcpPsRtpProcessor::on_rtp_packet(char* buf, int nb_buf, std::string ip, int port) -{ - srs_error_t err = srs_success; - bool completed = false; - - pprint->elapse(); - - char address_string[64] = {0}; - char port_string[16] = {0}; - /*if (getnameinfo(from, fromlen, - (char*)&address_string, sizeof(address_string), - (char*)&port_string, sizeof(port_string), - NI_NUMERICHOST | NI_NUMERICSERV)) { - return srs_error_new(ERROR_SYSTEM_IP_INVALID, "bad address"); - }*/ - - //itoa(port, port_string, 10); - int peer_port = port;// atoi(port_string); - - if (true) { - SrsBuffer stream(buf, nb_buf); - SrsPsRtpPacket pkt; - - if ((err = pkt.decode(&stream)) != srs_success) { - return srs_error_wrap(err, "ps rtp decode error"); - } - - //TODO: fixme: the same device uses the same SSRC to send with different local ports - std::stringstream ss; - ss << pkt.ssrc << ":" << pkt.timestamp << ":" << port;// port_string; - std::string pkt_key = ss.str(); - - std::stringstream ss2; - ss2 << pkt.ssrc << ":" << port_string; - std::string pre_pkt_key = ss2.str(); - - if (pre_packet.find(pre_pkt_key) == pre_packet.end()) { - pre_packet[pre_pkt_key] = new SrsPsRtpPacket(); - pre_packet[pre_pkt_key]->copy(&pkt); - } - //cache pkt by ssrc and timestamp - if (cache_ps_rtp_packet.find(pkt_key) == cache_ps_rtp_packet.end()) { - cache_ps_rtp_packet[pkt_key] = new SrsPsRtpPacket(); - } - - //get previous timestamp by ssrc - uint32_t pre_timestamp = pre_packet[pre_pkt_key]->timestamp; - uint32_t pre_sequence_number = pre_packet[pre_pkt_key]->sequence_number; - - //TODO: check sequence number out of order - //it may be out of order, or multiple streaming ssrc are the same - if (((pre_sequence_number + 1) % 65536) != pkt.sequence_number && - pre_sequence_number != pkt.sequence_number) { - srs_warn("gb28181: ps sequence_number out of order, ssrc=%#x, pre=%u, cur=%u, peer(%s, %s)", - pkt.ssrc, pre_sequence_number, pkt.sequence_number, ip.c_str(), port_string); - //return err; - } - - //copy header to cache - cache_ps_rtp_packet[pkt_key]->copy(&pkt); - //accumulate one frame of data, to payload cache - cache_ps_rtp_packet[pkt_key]->payload->append(pkt.payload); - - //detect whether it is a completed frame - if (pkt.marker) {// rtp maker is true, is a completed frame - completed = true; - } - else if (pre_timestamp != pkt.timestamp) { - //current timestamp is different from previous timestamp - //previous timestamp, is a completed frame - std::stringstream ss; - ss << pkt.ssrc << ":" << pre_timestamp << ":" << port_string; - pkt_key = ss.str(); - if (cache_ps_rtp_packet.find(pkt_key) != cache_ps_rtp_packet.end()) { - completed = true; - } - } - - if (pprint->can_print()) { - srs_trace("<- " SRS_CONSTS_LOG_GB28181_CASTER " gb28181: client_id %s, peer(%s, %d) ps rtp packet %dB, age=%d, vt=%d/%u, sts=%u/%u/%#x, paylod=%dB", - channel_id.c_str(), ip.c_str(), peer_port, nb_buf, pprint->age(), pkt.version, - pkt.payload_type, pkt.sequence_number, pkt.timestamp, pkt.ssrc, - pkt.payload->length() - ); - } - - //current packet becomes previous packet - srs_freep(pre_packet[pre_pkt_key]); - pre_packet[pre_pkt_key] = new SrsPsRtpPacket(); - pre_packet[pre_pkt_key]->copy(&pkt);; - - if (!completed) { - return err; - } - //process completed frame data - //clear processed one ps frame - //on completed frame data rtp packet in muxer enqueue - map::iterator key = cache_ps_rtp_packet.find(pkt_key); - if (key != cache_ps_rtp_packet.end()) - { - SrsGb28181RtmpMuxer* muxer = NULL; - //First, search according to the channel_id. Otherwise, search according to the SSRC. - //Some channel_id are created by RTP pool, which are different ports. - //No channel_id are created by multiplexing ports, which are the same port - if (!channel_id.empty()) { - muxer = _srs_gb28181->fetch_rtmpmuxer(channel_id); - } - else { - muxer = _srs_gb28181->fetch_rtmpmuxer_by_ssrc(pkt.ssrc); - } - - //auto crate channel - if (!muxer && config->auto_create_channel) { - //auto create channel generated id - std::stringstream ss, ss1; - ss << "chid" << pkt.ssrc; - std::string tmp_id = ss.str(); - - SrsGb28181StreamChannel channel; - channel.set_channel_id(tmp_id); - channel.set_port_mode(RTP_PORT_MODE_FIXED); - channel.set_ssrc(pkt.ssrc); - - srs_error_t err2 = srs_success; - if ((err2 = _srs_gb28181->create_stream_channel(&channel)) != srs_success) { - srs_warn("gb28181: RtpProcessor create stream channel error %s", srs_error_desc(err2).c_str()); - srs_error_reset(err2); - }; - - muxer = _srs_gb28181->fetch_rtmpmuxer(tmp_id); - } - - if (muxer) { - //TODO: fixme: the same device uses the same SSRC to send with different local ports - //record the first peer port - muxer->set_channel_peer_port(peer_port); - muxer->set_channel_peer_ip(address_string); - //not the first peer port's non processing - if (muxer->channel_peer_port() != peer_port) { - srs_warn("<- " SRS_CONSTS_LOG_GB28181_CASTER " gb28181: client_id %s, ssrc=%#x, first peer_port=%d cur peer_port=%d", - muxer->get_channel_id().c_str(), pkt.ssrc, muxer->channel_peer_port(), peer_port); - srs_freep(key->second); - } - else { - //put it in queue, wait for consumer to process, and then free - muxer->ps_packet_enqueue(key->second); - } - } - else { - //no consumer process it, discarded - srs_freep(key->second); - } - cache_ps_rtp_packet.erase(pkt_key); - } - } - return err; -} - -SrsGb28181RtmpMuxer* SrsGb28181TcpPsRtpProcessor::create_rtmpmuxer(std::string channel_id, uint32_t ssrc) -{ - if (true) { - SrsGb28181RtmpMuxer* muxer = NULL; - //First, search according to the channel_id. Otherwise, search according to the SSRC. - //Some channel_id are created by RTP pool, which are different ports. - //No channel_id are created by multiplexing ports, which are the same port - if (!channel_id.empty()) { - muxer = _srs_gb28181->fetch_rtmpmuxer(channel_id); - } - else { - muxer = _srs_gb28181->fetch_rtmpmuxer_by_ssrc(ssrc); - } - - //auto crate channel - if (!muxer && config->auto_create_channel) { - //auto create channel generated id - std::stringstream ss, ss1; - ss << "chid" << ssrc; - std::string tmp_id = ss.str(); - - SrsGb28181StreamChannel channel; - channel.set_channel_id(tmp_id); - channel.set_port_mode(RTP_PORT_MODE_FIXED); - channel.set_ssrc(ssrc); - - srs_error_t err2 = srs_success; - if ((err2 = _srs_gb28181->create_stream_channel(&channel)) != srs_success) { - srs_warn("gb28181: RtpProcessor create stream channel error %s", srs_error_desc(err2).c_str()); - srs_error_reset(err2); - }; - - muxer = _srs_gb28181->fetch_rtmpmuxer(tmp_id); - } - - return muxer; - }//end if FoundFrame -} - -srs_error_t SrsGb28181TcpPsRtpProcessor::rtmpmuxer_enqueue_data(SrsGb28181RtmpMuxer *muxer, uint32_t ssrc, - int peer_port, std::string address_string, SrsPsRtpPacket *pkt) -{ - srs_error_t err = srs_success; - - if (!muxer) - return err; - - if (muxer) { - //TODO: fixme: the same device uses the same SSRC to send with different local ports - //record the first peer port - muxer->set_channel_peer_port(peer_port); - muxer->set_channel_peer_ip(address_string); - //not the first peer port's non processing - if (muxer->channel_peer_port() != peer_port) { - srs_warn("<- " SRS_CONSTS_LOG_GB28181_CASTER " gb28181: client_id %s, ssrc=%#x, first peer_port=%d cur peer_port=%d", - muxer->get_channel_id().c_str(), ssrc, muxer->channel_peer_port(), peer_port); - } - else { - //muxer->ps_packet_enqueue(pkt); - muxer->insert_jitterbuffer(pkt); - }//end if (muxer->channel_peer_port() != peer_port) - }//end if (muxer) - - return err; -} - -srs_error_t SrsGb28181TcpPsRtpProcessor::on_rtp_packet_jitter(char* buf, int nb_buf, std::string ip, int port) -{ - srs_error_t err = srs_success; - - pprint->elapse(); - - char address_string[64] = {0}; - /*char port_string[16] = {0}; - if (getnameinfo(from, fromlen, - (char*)&address_string, sizeof(address_string), - (char*)&port_string, sizeof(port_string), - NI_NUMERICHOST | NI_NUMERICSERV)) { - return srs_error_new(ERROR_SYSTEM_IP_INVALID, "bad address"); - }*/ - - //itoa(port, port_string, 10); - int peer_port = port;// atoi(port_string); - - if (true) { - SrsBuffer stream(buf, nb_buf); - SrsPsRtpPacket *pkt = new SrsPsRtpPacket();; - - if ((err = pkt->decode(&stream)) != srs_success) { - srs_freep(pkt); - return srs_error_wrap(err, "ps rtp decode error"); - } - - std::stringstream ss3; - ss3 << pkt->ssrc << ":" << port;// port_string; - std::string jitter_key = ss3.str(); - - pkt->completed = pkt->marker; - - - if (pprint->can_print()) { - srs_trace("<- " SRS_CONSTS_LOG_GB28181_CASTER " SrsGb28181TcpPsRtpProcessor::on_rtp_packet_jitter gb28181: client_id %s, peer(%s, %d) ps rtp packet %dB, age=%d, vt=%d/%u, sts=%u/%u/%#x, paylod=%dB", - channel_id.c_str(), address_string, peer_port, nb_buf, pprint->age(), pkt->version, - pkt->payload_type, pkt->sequence_number, pkt->timestamp, pkt->ssrc, - pkt->payload->length() - ); - } - - SrsGb28181RtmpMuxer *muxer = create_rtmpmuxer(channel_id, pkt->ssrc); - if (muxer) { - rtmpmuxer_enqueue_data(muxer, pkt->ssrc, peer_port, ip, pkt); - } - - SrsAutoFree(SrsPsRtpPacket, pkt); - } - - return err; -} //ISrsPsStreamHander ps stream raw video/audio hander interface ISrsPsStreamHander::ISrsPsStreamHander() @@ -2830,9 +2507,10 @@ srs_error_t SrsGb28181Manger::query_device_list(std::string id, SrsJsonArray* ar return sip_service->query_device_list(id, arr); } - -#define SRS_RTSP_BUFFER 262144 -SrsGb28181Conn::SrsGb28181Conn(SrsGb28181Caster* c, srs_netfd_t fd, SrsGb28181TcpPsRtpProcessor *rtp_processor) +#define SRS_RTSP_BUFFER 8192 +#define RTP_TCP_HEADER 2 +#define MAX_PACKAGE_SIZE 1024 * 10 +SrsGb28181Conn::SrsGb28181Conn(SrsGb28181Caster* c, srs_netfd_t fd, SrsGb28181PsRtpProcessor *rtp_processor) { caster = c; stfd = fd; @@ -2877,90 +2555,64 @@ srs_error_t SrsGb28181Conn::do_cycle() { srs_error_t err = srs_success; - // retrieve ip of client. - int fd = srs_netfd_fileno(stfd); - std::string ip = srs_get_peer_ip(fd); - int port = srs_get_peer_port(fd); + // retrieve ip of client. + int fd = srs_netfd_fileno(stfd); + std::string ip = srs_get_peer_ip(fd); + int port = srs_get_peer_port(fd); + int addr_len = sizeof(sockaddr_in); + sockaddr_in *peer_sockaddr = (sockaddr_in*)malloc(addr_len); + peer_sockaddr->sin_family = AF_INET; //设置地址家族 + peer_sockaddr->sin_port = htons(port); //设置端口 + peer_sockaddr->sin_addr.s_addr = inet_addr(ip.c_str()); - if (ip.empty() && !_srs_config->empty_ip_ok()) { - srs_warn("empty ip for fd=%d", srs_netfd_fileno(stfd)); - } - srs_trace("rtsp: serve %s:%d", ip.c_str(), port); - char* leftData = (char*)malloc(SRS_RTSP_BUFFER);; - uint32_t leftDataLength = 0; - int16_t length = 0; - char* pp = (char*)&length; - char* p = &(mbuffer[0]); - ssize_t nb_read = 0; - int16_t length2; + if (ip.empty() && !_srs_config->empty_ip_ok()) { + srs_warn("empty ip for fd=%d", srs_netfd_fileno(stfd)); + } + srs_trace("gb28181 new connect by rtp-tcp from: %s:%d", ip.c_str(), port); - // consume all rtp data. - while (true) { - if ((err = trd->pull()) != srs_success) { - free(leftData); - return srs_error_wrap(err, "rtsp cycle"); - } + uint32_t left_data_len = 0; //缓存剩余数据 + ssize_t nb_read = 0; + uint16_t packet_len = 0; //rtp包长度 - //memset(buffer, 0, SRS_RTSP_BUFFER); - nb_read = 0; - if ((err = skt->read(mbuffer + leftDataLength, SRS_RTSP_BUFFER - leftDataLength, &nb_read)) != srs_success) { - free(leftData); - return srs_error_wrap(err, "recv data"); - } + // consume all rtp data. + while (true) { + if ((err = trd->pull()) != srs_success) { + return srs_error_wrap(err, "rtsp cycle"); + } + nb_read = 0; + if ((err = skt->read(mbuffer + left_data_len, SRS_RTSP_BUFFER - left_data_len, &nb_read)) != srs_success) { + return srs_error_wrap(err, "recv data"); + } - nb_read = nb_read + leftDataLength; - - pp = (char*)&length; - p = &(mbuffer[0]); - pp[1] = *p++; - pp[0] = *p++; + left_data_len = nb_read + left_data_len; + char * buf = mbuffer; - if (nb_read < (length + 2)) {//Not enough one packet. - leftDataLength = leftDataLength + nb_read; - continue; - } + uint32_t index = 0; + for( ; index < left_data_len; ){ + if (index + RTP_TCP_HEADER >= left_data_len){ //less rtp package + break; + } + packet_len = (((uint8_t *) buf)[index] << 8) | ((uint8_t *) buf)[index + 1]; + if (packet_len > MAX_PACKAGE_SIZE){ + //FIXME 自动重新invite? + srs_error("abnormal RTP packet length:%d, close the tcp conn:%s", packet_len, remote_ip().c_str()); + return err; + } + if (index + RTP_TCP_HEADER + packet_len >= left_data_len){ + break; + } + processor->on_tcp_packet((sockaddr*)peer_sockaddr, addr_len, buf + index + RTP_TCP_HEADER, packet_len); + index = index + RTP_TCP_HEADER + packet_len; + } + if (index != 0) { //update left data + left_data_len = left_data_len - index; + memmove(mbuffer, buf + index, left_data_len); + } - memset(leftData, 0, SRS_RTSP_BUFFER); - - while (length > 0) { - if ((length + 2) == nb_read) {//Only one packet. - nb_read = nb_read - 2; - processor->on_rtp(mbuffer + 2, nb_read, ip, port); - leftDataLength = 0; - break; - } - else { //multi packets. - pp = (char*)&length2; - p = &(mbuffer[length + 2]); - pp[1] = *p++; - pp[0] = *p++; - - processor->on_rtp(mbuffer + 2, length, ip, port); - - leftDataLength = nb_read - (length + 2); - nb_read = leftDataLength; - memcpy(leftData, mbuffer + length + 2, leftDataLength); - - pp = (char*)&length; - p = &(mbuffer[length + 2]); - pp[1] = *p++; - pp[0] = *p++; - - if (leftDataLength < (length + 2)) {//Not enough one packet. - memcpy(mbuffer, leftData, leftDataLength); - break; - } - else { - memcpy(mbuffer, leftData, leftDataLength); - } - } - } - } - - free(leftData); - - return err; + } + free(peer_sockaddr); + return err; } srs_error_t SrsGb28181Conn::cycle() @@ -2996,7 +2648,7 @@ SrsGb28181Caster::SrsGb28181Caster(SrsConfDirective* c) // TODO: FIXME: support reload. output = _srs_config->get_stream_caster_output(c); config = new SrsGb28181Config(c); - rtp_processor = new SrsGb28181TcpPsRtpProcessor(config, ""); + rtp_processor = new SrsGb28181PsRtpProcessor(config, ""); manager = new SrsResourceManager("GB28181TCP", true); } diff --git a/trunk/src/app/srs_app_gb28181.hpp b/trunk/src/app/srs_app_gb28181.hpp index 07bd0cfa2..04283bc27 100644 --- a/trunk/src/app/srs_app_gb28181.hpp +++ b/trunk/src/app/srs_app_gb28181.hpp @@ -94,7 +94,6 @@ class SrsSipRequest; class SrsGb28181RtmpMuxer; class SrsGb28181Config; class SrsGb28181PsRtpProcessor; -class SrsGb28181TcpPsRtpProcessor; class SrsGb28181SipService; class SrsGb28181StreamChannel; class SrsGb28181SipSession; @@ -176,37 +175,12 @@ private: // Interface ISrsUdpHandler public: virtual srs_error_t on_udp_packet(const sockaddr* from, const int fromlen, char* buf, int nb_buf); + virtual srs_error_t on_tcp_packet(const sockaddr* from, const int fromlen, char* buf, int nb_buf); public: virtual srs_error_t on_rtp_packet_jitter(const sockaddr* from, const int fromlen, char* buf, int nb_buf); virtual srs_error_t on_rtp_packet(const sockaddr* from, const int fromlen, char* buf, int nb_buf); }; -class SrsGb28181TcpPsRtpProcessor -{ -private: - SrsPithyPrint* pprint; - SrsGb28181Config* config; - std::map cache_ps_rtp_packet; - std::map pre_packet; - std::string channel_id; - bool auto_create_channel; -public: - SrsGb28181TcpPsRtpProcessor(SrsGb28181Config* c, std::string sid); - virtual ~SrsGb28181TcpPsRtpProcessor(); -private: - bool can_send_ps_av_packet(); - void dispose(); - void clear_pre_packet(); - SrsGb28181RtmpMuxer* create_rtmpmuxer(std::string channel_id, uint32_t ssrc); - srs_error_t rtmpmuxer_enqueue_data(SrsGb28181RtmpMuxer *muxer, uint32_t ssrc, - int peer_port, std::string address_string, SrsPsRtpPacket *pkt); - // Interface ISrsTcpHandler -public: - virtual srs_error_t on_rtp(char* buf, int nb_buf, std::string ip, int port); -public: - virtual srs_error_t on_rtp_packet_jitter(char* buf, int nb_buf, std::string ip, int port); - virtual srs_error_t on_rtp_packet(char* buf, int nb_buf, std::string ip, int port); -}; //ps stream processing parsing interface class ISrsPsStreamHander @@ -581,9 +555,9 @@ private: SrsRtspStack* rtsp; SrsGb28181Caster* caster; SrsCoroutine* trd; - SrsGb28181TcpPsRtpProcessor *processor; + SrsGb28181PsRtpProcessor *processor; public: - SrsGb28181Conn(SrsGb28181Caster* c, srs_netfd_t fd, SrsGb28181TcpPsRtpProcessor *rtp_processor); + SrsGb28181Conn(SrsGb28181Caster* c, srs_netfd_t fd, SrsGb28181PsRtpProcessor *rtp_processor); virtual ~SrsGb28181Conn(); public: virtual srs_error_t serve(); @@ -603,7 +577,7 @@ class SrsGb28181Caster : public ISrsTcpHandler private: std::string output; SrsGb28181Config *config; - SrsGb28181TcpPsRtpProcessor *rtp_processor; + SrsGb28181PsRtpProcessor *rtp_processor; private: std::vector clients; SrsResourceManager* manager; From cc52e5b27c5243b0fb6938717d9b162351276f83 Mon Sep 17 00:00:00 2001 From: "louis.xia" <68469352@qq.com> Date: Fri, 28 May 2021 21:38:12 +0800 Subject: [PATCH 3/3] GB28181: Fix parse rtp tcp failed (#2382) * fix parse rtp-tcp failed * fix parse rtp-tcp failed * fix gb28181 support tcp stack is setup:passive * Update push.gb28181.tcp.conf Co-authored-by: cfw Co-authored-by: Winlin --- trunk/conf/push.gb28181.tcp.conf | 143 ++++++++++++++++++++++++ trunk/src/app/srs_app_gb28181_stack.cpp | 2 + 2 files changed, 145 insertions(+) create mode 100644 trunk/conf/push.gb28181.tcp.conf diff --git a/trunk/conf/push.gb28181.tcp.conf b/trunk/conf/push.gb28181.tcp.conf new file mode 100644 index 000000000..257195afd --- /dev/null +++ b/trunk/conf/push.gb28181.tcp.conf @@ -0,0 +1,143 @@ +# push gb28181 stream to SRS. + +listen 1935; +max_connections 1000; +daemon off; +srs_log_tank console; + +http_api { + enabled on; + listen 1985; +} + +http_server { + enabled on; + listen 8080; +} + +stats { + network 0; +} + +stream_caster { + enabled on; + caster gb28181; + + # 转发流到rtmp服务器地址与端口 + # TODO: https://github.com/ossrs/srs/pull/1679/files#r400875104 + # [stream] is VideoChannelCodecID(视频通道编码ID) for sip + # 自动创建的道通[stream] 是‘chid[ssrc]’ [ssrc]是rtp的ssrc + # [ssrc] rtp中的ssrc + output rtmp://127.0.0.1:1935/live/[stream]; + + # 接收设备端rtp流的多路复用端口 + listen 9000; + # 多路复用端口类型,on为tcp,off为udp + # 默认:off + tcp_enable on; + + # rtp接收监听端口范围,最小值 + rtp_port_min 58200; + # rtp接收监听端口范围,最大值 + rtp_port_max 58300; + + # 是否等待关键帧之后,再转发, + # off:不需等待,直接转发 + # on:等第一个关键帧后,再转发 + wait_keyframe on; + + # rtp包空闲等待时间,如果指定时间没有收到任何包 + # rtp监听连接自动停止,发送BYE命令 + rtp_idle_timeout 30; + + # 是否转发音频流 + # 目前只支持aac格式,所以需要设备支持aac格式 + # on:转发音频 + # off:不转发音频,只有视频 + # *注意*!!!:flv 只支持11025 22050 44100 三种 + # 如果设备端没有三种中任何一个,转发时为自动选择一种格式 + # 同时也会将adts的头封装在flv aac raw数据中 + # 这样的话播放器为自动通过adts头自动选择采样频率 + # 像ffplay, vlc都可以,但是flash是没有声音, + # 因为flash,只支持11025 22050 44100 + audio_enable off; + + # 是否开启rtp缓冲 + # 开启之后能有效解决rtp乱序等问题 + # tcp模式建议关闭 + jitterbuffer_enable off; + + # 服务器主机号,可以域名或ip地址 + # 也就是设备端将媒体发送的地址,如果是服务器是内外网 + # 需要写外网地址, + # 调用api创建stream session时返回ip地址也是host + # $CANDIDATE 是系统环境变量,从环境变量获取地址,如果没有配置,用* + # *代表指定stats network 的网卡号地址,如果没有配置network,默认则是第0号网卡地址 + # TODO: https://github.com/ossrs/srs/pull/1679/files#r400917594 + host $CANDIDATE; + + #根据收到ps rtp包自带创建rtmp媒体通道,不需要api接口创建 + #rtmp地址参数[stream] 就是通道id 格式chid[ssrc] + auto_create_channel off; + + sip { + # 是否启用srs内部sip信令 + # 为on信令走srs, off 只转发ps流 + enabled on; + + # sip监听udp端口 + listen 5060; + + # SIP server ID(SIP服务器ID). + # 设备端配置编号需要与该值一致,否则无法注册 + serial 34020000002000000001; + + # SIP server domain(SIP服务器域) + realm 3402000000; + + # 服务端发送ack后,接收回应的超时时间,单位为秒 + # 如果指定时间没有回应,认为失败 + ack_timeout 30; + + # 设备心跳维持时间,如果指定时间内(秒)没有接收一个心跳 + # 认为设备离线 + keepalive_timeout 120; + + # 注册之后是否自动给设备端发送invite + # on: 是 off 不是,需要通过api控制 + auto_play on; + # 设备将流发送的端口,是否固定 + # on 发送流到多路复用端口 如9000 + # off 自动从rtp_mix_port - rtp_max_port 之间的值中 + # 选一个可以用的端口 + invite_port_fixed on; + + # 向设备或下级域查询设备列表的间隔,单位(秒) + # 默认60秒 + query_catalog_interval 60; + } +} + +rtc_server { + enabled on; + # Listen at udp://8000 + listen 8000; + # + # The $CANDIDATE means fetch from env, if not configed, use * as default. + # + # The * means retrieving server IP automatically, from all network interfaces, + # @see https://github.com/ossrs/srs/issues/307#issuecomment-599028124 + candidate $CANDIDATE; +} + +vhost __defaultVhost__ { + rtc { + enabled on; + bframe discard; + } + + http_remux { + enabled on; + mount [vhost]/[app]/[stream].flv; + } +} diff --git a/trunk/src/app/srs_app_gb28181_stack.cpp b/trunk/src/app/srs_app_gb28181_stack.cpp index c5bcfda0c..8d0c81b9d 100644 --- a/trunk/src/app/srs_app_gb28181_stack.cpp +++ b/trunk/src/app/srs_app_gb28181_stack.cpp @@ -1062,6 +1062,8 @@ void SrsSipStack::req_invite(stringstream& ss, SrsSipRequest *req, string ip, in //<< "m=video " << port << " TCP/RTP/AVP 98" << SRS_RTSP_CRLF << "a=recvonly" << SRS_RTSP_CRLF << "a=rtpmap:96 PS/90000" << SRS_RTSP_CRLF + << "a=setup:passive" << SRS_RTSP_CRLF + << "a=connection:new" << SRS_RTSP_CRLF //TODO: current no support //<< "a=rtpmap:97 MPEG4/90000" << SRS_RTSP_CRLF //<< "a=rtpmap:98 H264/90000" << SRS_RTSP_CRLF