mirror of https://github.com/ossrs/srs.git
Squash: Move GB28181 to feature/gb28181. 5.0.4
parent
49826081b1
commit
efdbf37255
File diff suppressed because it is too large
Load Diff
@ -1,581 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2013-2021 Lixin
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#ifndef SRS_APP_GB28181_HPP
|
||||
#define SRS_APP_GB28181_HPP
|
||||
|
||||
#include <srs_core.hpp>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <map>
|
||||
|
||||
#include <srs_app_st.hpp>
|
||||
#include <srs_app_listener.hpp>
|
||||
#include <srs_kernel_stream.hpp>
|
||||
#include <srs_app_log.hpp>
|
||||
#include <srs_kernel_file.hpp>
|
||||
#include <srs_protocol_json.hpp>
|
||||
#include <srs_app_gb28181_sip.hpp>
|
||||
#include <srs_app_gb28181_jitter.hpp>
|
||||
#include <srs_rtmp_stack.hpp>
|
||||
#include <srs_app_source.hpp>
|
||||
#include <srs_service_conn.hpp>
|
||||
|
||||
#define RTP_PORT_MODE_FIXED "fixed"
|
||||
#define RTP_PORT_MODE_RANDOM "random"
|
||||
|
||||
#define PS_AUDIO_ID 0xc0
|
||||
#define PS_AUDIO_ID_END 0xdf
|
||||
#define PS_VIDEO_ID 0xe0
|
||||
#define PS_VIDEO_ID_END 0xef
|
||||
|
||||
#define STREAM_TYPE_VIDEO_MPEG1 0x01
|
||||
#define STREAM_TYPE_VIDEO_MPEG2 0x02
|
||||
#define STREAM_TYPE_AUDIO_MPEG1 0x03
|
||||
#define STREAM_TYPE_AUDIO_MPEG2 0x04
|
||||
#define STREAM_TYPE_PRIVATE_SECTION 0x05
|
||||
#define STREAM_TYPE_PRIVATE_DATA 0x06
|
||||
#define STREAM_TYPE_AUDIO_AAC 0x0f
|
||||
#define STREAM_TYPE_VIDEO_MPEG4 0x10
|
||||
#define STREAM_TYPE_VIDEO_H264 0x1b
|
||||
#define STREAM_TYPE_VIDEO_HEVC 0x24
|
||||
#define STREAM_TYPE_VIDEO_CAVS 0x42
|
||||
#define STREAM_TYPE_VIDEO_SAVC 0x80
|
||||
|
||||
#define STREAM_TYPE_AUDIO_AC3 0x81
|
||||
|
||||
#define STREAM_TYPE_AUDIO_G711 0x90
|
||||
#define STREAM_TYPE_AUDIO_G711ULAW 0x91
|
||||
#define STREAM_TYPE_AUDIO_G722_1 0x92
|
||||
#define STREAM_TYPE_AUDIO_G723_1 0x93
|
||||
#define STREAM_TYPE_AUDIO_G726 0x96
|
||||
#define STREAM_TYPE_AUDIO_G729_1 0x99
|
||||
#define STREAM_TYPE_AUDIO_SVAC 0x9b
|
||||
#define STREAM_TYPE_AUDIO_PCM 0x9c
|
||||
|
||||
class SrsConfDirective;
|
||||
class SrsRtspPacket;
|
||||
class SrsRtmpClient;
|
||||
class SrsRawH264Stream;
|
||||
class SrsRawAacStream;
|
||||
struct SrsRawAacStreamCodec;
|
||||
class SrsSharedPtrMessage;
|
||||
class SrsAudioFrame;
|
||||
class SrsSimpleStream;
|
||||
class SrsPithyPrint;
|
||||
class SrsSimpleRtmpClient;
|
||||
class SrsSipStack;
|
||||
class SrsGb28181Manger;
|
||||
class SrsRtpTimeJitter;
|
||||
class SrsSipRequest;
|
||||
class SrsGb28181RtmpMuxer;
|
||||
class SrsGb28181Config;
|
||||
class SrsGb28181PsRtpProcessor;
|
||||
class SrsGb28181SipService;
|
||||
class SrsGb28181StreamChannel;
|
||||
class SrsGb28181SipSession;
|
||||
class SrsRtpJitterBuffer;
|
||||
class SrsServer;
|
||||
class SrsLiveSource;
|
||||
class SrsRequest;
|
||||
class SrsResourceManager;
|
||||
class SrsGb28181Conn;
|
||||
class SrsGb28181Caster;
|
||||
|
||||
//ps rtp header packet parse
|
||||
|
||||
class SrsPsRtpPacket: public SrsRtspPacket
|
||||
{
|
||||
public:
|
||||
SrsPsRtpPacket();
|
||||
virtual ~SrsPsRtpPacket();
|
||||
bool isFirstPacket;
|
||||
public:
|
||||
virtual srs_error_t decode(SrsBuffer* stream);
|
||||
};
|
||||
|
||||
//randomly assigned ports receive gb28181 device streams
|
||||
class SrsPsRtpListener: public ISrsUdpHandler
|
||||
{
|
||||
private:
|
||||
SrsUdpListener* listener;
|
||||
SrsGb28181PsRtpProcessor* rtp_processor;
|
||||
int _port;
|
||||
public:
|
||||
SrsPsRtpListener(SrsGb28181Config* c, int p, std::string s);
|
||||
virtual ~SrsPsRtpListener();
|
||||
public:
|
||||
virtual int port();
|
||||
virtual srs_error_t listen();
|
||||
// Interface ISrsUdpHandler
|
||||
public:
|
||||
virtual srs_error_t on_udp_packet(const sockaddr* from, const int fromlen, char* buf, int nb_buf);
|
||||
};
|
||||
|
||||
//multiplexing service, single port receiving all gb28181 device streams
|
||||
class SrsGb28181RtpMuxService : public ISrsUdpHandler
|
||||
{
|
||||
private:
|
||||
SrsGb28181Config *config;
|
||||
SrsGb28181PsRtpProcessor *rtp_processor;
|
||||
public:
|
||||
SrsGb28181RtpMuxService(SrsConfDirective* c);
|
||||
virtual ~SrsGb28181RtpMuxService();
|
||||
|
||||
// Interface ISrsUdpHandler
|
||||
public:
|
||||
virtual srs_error_t on_udp_packet(const sockaddr* from, const int fromlen, char* buf, int nb_buf);
|
||||
};
|
||||
|
||||
|
||||
//process gb28181 RTP package, generate a completed PS stream data,
|
||||
//call the PS stream parser, parse the original video and audio
|
||||
class SrsGb28181PsRtpProcessor: public ISrsUdpHandler
|
||||
{
|
||||
private:
|
||||
SrsPithyPrint* pprint;
|
||||
SrsGb28181Config* config;
|
||||
std::map<std::string, SrsPsRtpPacket*> cache_ps_rtp_packet;
|
||||
std::map<std::string, SrsPsRtpPacket*> pre_packet;
|
||||
std::string channel_id;
|
||||
bool auto_create_channel;
|
||||
public:
|
||||
SrsGb28181PsRtpProcessor(SrsGb28181Config* c, std::string sid);
|
||||
virtual ~SrsGb28181PsRtpProcessor();
|
||||
private:
|
||||
bool can_send_ps_av_packet();
|
||||
void dispose();
|
||||
void clear_pre_packet();
|
||||
SrsGb28181RtmpMuxer* fetch_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 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);
|
||||
};
|
||||
|
||||
|
||||
//ps stream processing parsing interface
|
||||
class ISrsPsStreamHander
|
||||
{
|
||||
public:
|
||||
ISrsPsStreamHander();
|
||||
virtual ~ISrsPsStreamHander();
|
||||
public:
|
||||
virtual srs_error_t on_rtp_video(SrsSimpleStream* stream, int64_t dts)=0;
|
||||
virtual srs_error_t on_rtp_audio(SrsSimpleStream* stream, int64_t dts, int type)=0;
|
||||
};
|
||||
|
||||
//analysis of PS stream and
|
||||
//extraction of H264 raw data and audio data
|
||||
//then process the flow through PS stream hander,
|
||||
//such as RTMP multiplexer, and composited into RTMP av stream
|
||||
class SrsPsStreamDemixer
|
||||
{
|
||||
public:
|
||||
// gb28181 program stream struct define
|
||||
struct SrsPsPacketStartCode
|
||||
{
|
||||
uint8_t start_code[3];
|
||||
uint8_t stream_id[1];
|
||||
};
|
||||
|
||||
struct SrsPsPacketHeader
|
||||
{
|
||||
SrsPsPacketStartCode start;// 4
|
||||
uint8_t info[9];
|
||||
uint8_t stuffing_length;
|
||||
};
|
||||
|
||||
struct SrsPsPacketBBHeader
|
||||
{
|
||||
SrsPsPacketStartCode start;
|
||||
uint16_t length;
|
||||
};
|
||||
|
||||
struct SrsPsePacket
|
||||
{
|
||||
SrsPsPacketStartCode start;
|
||||
uint16_t length;
|
||||
uint8_t info[2];
|
||||
uint8_t stuffing_length;
|
||||
};
|
||||
|
||||
struct SrsPsMapPacket
|
||||
{
|
||||
SrsPsPacketStartCode start;
|
||||
uint16_t length;
|
||||
};
|
||||
|
||||
private:
|
||||
SrsFileWriter ps_fw;
|
||||
SrsFileWriter video_fw;
|
||||
SrsFileWriter audio_fw;
|
||||
SrsFileWriter unknow_fw;
|
||||
|
||||
bool first_keyframe_flag;
|
||||
bool wait_first_keyframe;
|
||||
bool audio_enable;
|
||||
std::string channel_id;
|
||||
|
||||
uint8_t video_es_id;
|
||||
uint8_t video_es_type;
|
||||
uint8_t audio_es_id;
|
||||
uint8_t audio_es_type;
|
||||
int audio_check_aac_try_count;
|
||||
|
||||
SrsRawAacStream *aac;
|
||||
|
||||
ISrsPsStreamHander *hander;
|
||||
public:
|
||||
SrsPsStreamDemixer(ISrsPsStreamHander *h, std::string sid, bool a, bool k);
|
||||
virtual ~SrsPsStreamDemixer();
|
||||
private:
|
||||
bool can_send_ps_av_packet();
|
||||
public:
|
||||
int64_t parse_ps_timestamp(const uint8_t* p);
|
||||
std::string get_ps_map_type_str(uint8_t);
|
||||
virtual srs_error_t on_ps_stream(char* ps_data, int ps_size, uint32_t timestamp, uint32_t ssrc);
|
||||
};
|
||||
|
||||
|
||||
//RTMP multiplexer, which processes the raw H264 / AAC,
|
||||
//then publish it to RTMP server
|
||||
class SrsGb28181RtmpMuxer : public ISrsCoroutineHandler,
|
||||
public ISrsConnection, public ISrsPsStreamHander
|
||||
{
|
||||
private:
|
||||
SrsPithyPrint* pprint;
|
||||
SrsGb28181StreamChannel *channel;
|
||||
int stream_idle_timeout;
|
||||
srs_utime_t recv_rtp_stream_time;
|
||||
srs_utime_t send_rtmp_stream_time;
|
||||
private:
|
||||
std::string channel_id;
|
||||
std::string _rtmp_url;
|
||||
std::string video_ssrc;
|
||||
std::string audio_ssrc;
|
||||
|
||||
SrsGb28181Manger* gb28181_manger;
|
||||
SrsCoroutine* trd;
|
||||
SrsPsStreamDemixer* ps_demixer;
|
||||
srs_cond_t wait_ps_queue;
|
||||
|
||||
SrsSimpleRtmpClient* sdk;
|
||||
SrsRtpTimeJitter* vjitter;
|
||||
SrsRtpTimeJitter* ajitter;
|
||||
|
||||
SrsRawH264Stream* avc;
|
||||
std::string h264_sps;
|
||||
std::string h264_pps;
|
||||
|
||||
SrsRawAacStream* aac;
|
||||
std::string aac_specific_config;
|
||||
|
||||
SrsRequest* req;
|
||||
SrsLiveSource* source;
|
||||
SrsServer* server;
|
||||
|
||||
SrsRtpJitterBuffer *jitter_buffer;
|
||||
SrsRtpJitterBuffer *jitter_buffer_audio;
|
||||
|
||||
char *ps_buffer;
|
||||
char *ps_buffer_audio;
|
||||
|
||||
int ps_buflen;
|
||||
int ps_buflen_auido;
|
||||
|
||||
uint32_t ps_rtp_video_ts;
|
||||
|
||||
bool source_publish;
|
||||
|
||||
public:
|
||||
std::queue<SrsPsRtpPacket*> ps_queue;
|
||||
|
||||
public:
|
||||
SrsGb28181RtmpMuxer(SrsGb28181Manger* m, std::string id, bool a, bool k);
|
||||
virtual ~SrsGb28181RtmpMuxer();
|
||||
|
||||
public:
|
||||
virtual srs_error_t serve();
|
||||
virtual void stop();
|
||||
srs_error_t initialize(SrsServer* s, SrsRequest* r);
|
||||
|
||||
virtual std::string get_channel_id();
|
||||
virtual void ps_packet_enqueue(SrsPsRtpPacket *pkt);
|
||||
virtual void copy_channel(SrsGb28181StreamChannel *s);
|
||||
virtual void set_channel_peer_ip(std::string ip);
|
||||
virtual void set_channel_peer_port(int port);
|
||||
virtual int channel_peer_port();
|
||||
virtual std::string channel_peer_ip();
|
||||
virtual void set_rtmp_url(std::string url);
|
||||
virtual std::string rtmp_url();
|
||||
virtual SrsGb28181StreamChannel get_channel();
|
||||
srs_utime_t get_recv_stream_time();
|
||||
|
||||
void insert_jitterbuffer(SrsPsRtpPacket *pkt);
|
||||
|
||||
private:
|
||||
virtual srs_error_t do_cycle();
|
||||
virtual void destroy();
|
||||
|
||||
// Interface ISrsOneCycleThreadHandler
|
||||
public:
|
||||
virtual srs_error_t cycle();
|
||||
// Interface ISrsConnection.
|
||||
public:
|
||||
virtual std::string remote_ip();
|
||||
virtual const SrsContextId& get_id();
|
||||
virtual std::string desc();
|
||||
public:
|
||||
virtual srs_error_t on_rtp_video(SrsSimpleStream* stream, int64_t dts);
|
||||
virtual srs_error_t on_rtp_audio(SrsSimpleStream* stream, int64_t dts, int type);
|
||||
private:
|
||||
|
||||
srs_error_t replace_startcode_with_nalulen(char *video_data, int &size, uint32_t pts, uint32_t dts);
|
||||
srs_error_t write_h264_ipb_frame2(char *frame, int frame_size, uint32_t pts, uint32_t dts);
|
||||
virtual srs_error_t write_h264_sps_pps(uint32_t dts, uint32_t pts);
|
||||
virtual srs_error_t write_h264_ipb_frame(char* frame, int frame_size, uint32_t dts, uint32_t pts, bool b = true);
|
||||
virtual srs_error_t write_audio_raw_frame(char* frame, int frame_size, SrsRawAacStreamCodec* codec, uint32_t dts);
|
||||
virtual srs_error_t rtmp_write_packet(char type, uint32_t timestamp, char* data, int size);
|
||||
virtual srs_error_t rtmp_write_packet_by_source(char type, uint32_t timestamp, char* data, int size);
|
||||
private:
|
||||
// Connect to RTMP server.
|
||||
virtual srs_error_t connect();
|
||||
// Close the connection to RTMP server.
|
||||
virtual void close();
|
||||
public:
|
||||
virtual void rtmp_close();
|
||||
};
|
||||
|
||||
//system parameter configuration of gb28181 module,
|
||||
//read file from configuration file to generate
|
||||
class SrsGb28181Config
|
||||
{
|
||||
public:
|
||||
std::string host;
|
||||
srs_utime_t rtp_idle_timeout;
|
||||
bool audio_enable;
|
||||
bool wait_keyframe;
|
||||
std::string output;
|
||||
int rtp_port_min;
|
||||
int rtp_port_max;
|
||||
int rtp_mux_port;
|
||||
bool rtp_mux_tcp_enable;
|
||||
bool auto_create_channel;
|
||||
bool jitterbuffer_enable;
|
||||
|
||||
//sip config
|
||||
int sip_port;
|
||||
std::string sip_serial;
|
||||
std::string sip_realm;
|
||||
bool sip_enable;
|
||||
srs_utime_t sip_ack_timeout;
|
||||
srs_utime_t sip_keepalive_timeout;
|
||||
bool sip_auto_play;
|
||||
bool sip_invite_port_fixed;
|
||||
srs_utime_t sip_query_catalog_interval;
|
||||
|
||||
public:
|
||||
SrsGb28181Config(SrsConfDirective* c);
|
||||
virtual ~SrsGb28181Config();
|
||||
};
|
||||
|
||||
class SrsGb28181StreamChannel
|
||||
{
|
||||
private:
|
||||
std::string channel_id;
|
||||
std::string port_mode;
|
||||
std::string app;
|
||||
std::string stream;
|
||||
std::string rtmp_url;
|
||||
std::string flv_url;
|
||||
std::string hls_url;
|
||||
std::string webrtc_url;
|
||||
|
||||
std::string ip;
|
||||
int rtp_port;
|
||||
int rtmp_port;
|
||||
uint32_t ssrc;
|
||||
srs_utime_t recv_time;
|
||||
std::string recv_time_str;
|
||||
|
||||
//send rtp stream client local port
|
||||
int rtp_peer_port;
|
||||
//send rtp stream client local ip
|
||||
std::string rtp_peer_ip;
|
||||
|
||||
public:
|
||||
SrsGb28181StreamChannel();
|
||||
virtual ~SrsGb28181StreamChannel();
|
||||
|
||||
std::string get_channel_id() const { return channel_id; }
|
||||
std::string get_port_mode() const { return port_mode; }
|
||||
std::string get_app() const { return app; }
|
||||
std::string get_stream() const { return stream; }
|
||||
std::string get_ip() const { return ip; }
|
||||
int get_rtp_port() const { return rtp_port; }
|
||||
int get_rtmp_port() const { return rtmp_port; }
|
||||
uint32_t get_ssrc() const { return ssrc; }
|
||||
uint32_t get_rtp_peer_port() const { return rtp_peer_port; }
|
||||
std::string get_rtp_peer_ip() const { return rtp_peer_ip; }
|
||||
std::string get_rtmp_url() const { return rtmp_url; }
|
||||
std::string get_flv_url() const { return flv_url; }
|
||||
std::string get_hls_url() const { return hls_url; }
|
||||
std::string get_webrtc_url() const { return webrtc_url; }
|
||||
srs_utime_t get_recv_time() const { return recv_time; }
|
||||
std::string get_recv_time_str() const { return recv_time_str; }
|
||||
|
||||
void set_channel_id(const std::string &i) { channel_id = i; }
|
||||
void set_port_mode(const std::string &p) { port_mode = p; }
|
||||
void set_app(const std::string &a) { app = a; }
|
||||
void set_stream(const std::string &s) { stream = s; }
|
||||
void set_ip(const std::string &i) { ip = i; }
|
||||
void set_rtp_port( const int &p) { rtp_port = p; }
|
||||
void set_rtmp_port( const int &p) { rtmp_port = p; }
|
||||
void set_ssrc( const int &s) { ssrc = s;}
|
||||
void set_rtp_peer_ip( const std::string &p) { rtp_peer_ip = p; }
|
||||
void set_rtp_peer_port( const int &s) { rtp_peer_port = s;}
|
||||
void set_rtmp_url( const std::string &u) { rtmp_url = u; }
|
||||
void set_flv_url( const std::string &u) { flv_url = u; }
|
||||
void set_hls_url( const std::string &u) { hls_url = u; }
|
||||
void set_webrtc_url( const std::string &u) { webrtc_url = u; }
|
||||
void set_recv_time( const srs_utime_t &u) { recv_time = u; }
|
||||
void set_recv_time_str( const std::string &u) { recv_time_str = u; }
|
||||
|
||||
void copy(const SrsGb28181StreamChannel *s);
|
||||
void dumps(SrsJsonObject* obj);
|
||||
|
||||
};
|
||||
|
||||
// Global singleton instance.
|
||||
extern SrsGb28181Manger* _srs_gb28181;
|
||||
|
||||
//gb28181 module management, management of all RTMP multiplexers,
|
||||
//random assignment of RTP listeners, and external control interfaces
|
||||
class SrsGb28181Manger
|
||||
{
|
||||
private:
|
||||
SrsGb28181Config *config;
|
||||
// The key: port, value: whether used.
|
||||
std::map<int, bool> used_ports;
|
||||
std::map<uint32_t, SrsPsRtpListener*> rtp_pool;
|
||||
std::map<uint32_t, SrsGb28181RtmpMuxer*> rtmpmuxers_ssrc;
|
||||
std::map<std::string, SrsGb28181RtmpMuxer*> rtmpmuxers;
|
||||
SrsResourceManager* manager;
|
||||
SrsGb28181SipService* sip_service;
|
||||
SrsServer* server;
|
||||
public:
|
||||
SrsGb28181Manger(SrsServer* s, SrsConfDirective* c);
|
||||
virtual ~SrsGb28181Manger();
|
||||
|
||||
public:
|
||||
srs_error_t fetch_or_create_rtmpmuxer(std::string id, SrsRequest *req, SrsGb28181RtmpMuxer** gb28181);
|
||||
SrsGb28181RtmpMuxer* fetch_rtmpmuxer(std::string id);
|
||||
SrsGb28181RtmpMuxer* fetch_rtmpmuxer_by_ssrc(uint32_t ssrc);
|
||||
void update_rtmpmuxer_to_newssrc_by_id(std::string id, uint32_t ssrc);
|
||||
void rtmpmuxer_map_by_ssrc(SrsGb28181RtmpMuxer*muxer, uint32_t ssrc);
|
||||
void rtmpmuxer_unmap_by_ssrc(uint32_t ssrc);
|
||||
uint32_t generate_ssrc(std::string id);
|
||||
uint32_t hash_code(std::string str);
|
||||
|
||||
void set_sip_service(SrsGb28181SipService *s) { sip_service = s; }
|
||||
SrsGb28181SipService* get_sip_service() { return sip_service; }
|
||||
SrsGb28181Config* get_gb28181_config_ptr() { return config;}
|
||||
|
||||
public:
|
||||
//stream channel api
|
||||
srs_error_t create_stream_channel(SrsGb28181StreamChannel *channel);
|
||||
srs_error_t delete_stream_channel(std::string id, std::string chid);
|
||||
srs_error_t query_stream_channel(std::string id, SrsJsonArray* arr);
|
||||
//sip api
|
||||
srs_error_t notify_sip_invite(std::string id, std::string ip, int port, uint32_t ssrc, std::string chid);
|
||||
srs_error_t notify_sip_bye(std::string id, std::string chid);
|
||||
srs_error_t notify_sip_raw_data(std::string id, std::string data);
|
||||
srs_error_t notify_sip_unregister(std::string id);
|
||||
srs_error_t notify_sip_query_catalog(std::string id);
|
||||
srs_error_t notify_sip_ptz(std::string id, std::string chid, std::string cmd, uint8_t speed, int priority);
|
||||
srs_error_t query_sip_session(std::string id, SrsJsonArray* arr);
|
||||
srs_error_t query_device_list(std::string id, SrsJsonArray* arr);
|
||||
|
||||
private:
|
||||
void destroy();
|
||||
|
||||
public:
|
||||
// Alloc a rtp port from local ports pool.
|
||||
// @param pport output the rtp port.
|
||||
void alloc_port(int* pport);
|
||||
// Free the alloced rtp port.
|
||||
void free_port(int lpmin, int lpmax);
|
||||
srs_error_t initialize();
|
||||
|
||||
SrsGb28181Config get_gb28181_config();
|
||||
srs_error_t start_ps_rtp_listen(std::string id, int port);
|
||||
void stop_rtp_listen(std::string id);
|
||||
|
||||
public:
|
||||
void remove(SrsGb28181RtmpMuxer* conn);
|
||||
void remove_sip_session(SrsGb28181SipSession* sess);
|
||||
};
|
||||
|
||||
// The gb28181 tcp connection serve the fd.
|
||||
class SrsGb28181Conn : public ISrsCoroutineHandler, public ISrsConnection
|
||||
{
|
||||
private:
|
||||
char* mbuffer;
|
||||
srs_netfd_t stfd;
|
||||
SrsStSocket* skt;
|
||||
SrsRtspStack* rtsp;
|
||||
SrsGb28181Caster* caster;
|
||||
SrsCoroutine* trd;
|
||||
SrsGb28181PsRtpProcessor *processor;
|
||||
public:
|
||||
SrsGb28181Conn(SrsGb28181Caster* c, srs_netfd_t fd, SrsGb28181PsRtpProcessor *rtp_processor);
|
||||
virtual ~SrsGb28181Conn();
|
||||
public:
|
||||
virtual srs_error_t serve();
|
||||
virtual std::string remote_ip();
|
||||
private:
|
||||
virtual srs_error_t do_cycle();
|
||||
// Interface ISrsOneCycleThreadHandler
|
||||
public:
|
||||
virtual srs_error_t cycle();
|
||||
virtual std::string desc();
|
||||
virtual const SrsContextId& get_id();
|
||||
};
|
||||
|
||||
// The caster for gb28181.
|
||||
class SrsGb28181Caster : public ISrsTcpHandler
|
||||
{
|
||||
private:
|
||||
std::string output;
|
||||
SrsGb28181Config *config;
|
||||
SrsGb28181PsRtpProcessor *rtp_processor;
|
||||
private:
|
||||
std::vector<SrsGb28181Conn*> clients;
|
||||
SrsResourceManager* manager;
|
||||
public:
|
||||
SrsGb28181Caster(SrsConfDirective* c);
|
||||
virtual ~SrsGb28181Caster();
|
||||
public:
|
||||
virtual srs_error_t initialize();
|
||||
// Interface ISrsTcpHandler
|
||||
public:
|
||||
virtual srs_error_t on_tcp_client(srs_netfd_t stfd);
|
||||
// internal methods.
|
||||
public:
|
||||
virtual void remove(SrsGb28181Conn* conn);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,530 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2013-2021 Lixin
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#ifndef SRS_APP_GB28181_RTP_JITBUFFER_HPP
|
||||
#define SRS_APP_GB28181_RTP_JITBUFFER_HPP
|
||||
|
||||
#include <srs_core.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <set>
|
||||
|
||||
#include <srs_app_log.hpp>
|
||||
#include <srs_kernel_utility.hpp>
|
||||
#include <srs_kernel_rtc_rtp.hpp>
|
||||
#include <srs_kernel_flv.hpp>
|
||||
|
||||
class SrsPsRtpPacket;
|
||||
class SrsRtpFrameBuffer;
|
||||
class SrsRtpDecodingState;
|
||||
class SrsGb28181RtmpMuxer;
|
||||
class VCMPacket;
|
||||
class SrsRtpPacket;
|
||||
|
||||
///jittbuffer
|
||||
|
||||
enum FrameType {
|
||||
kEmptyFrame = 0,
|
||||
kAudioFrameSpeech = 1,
|
||||
kAudioFrameCN = 2,
|
||||
kVideoFrameKey = 3, // independent frame
|
||||
kVideoFrameDelta = 4, // depends on the previus frame
|
||||
kVideoFrameGolden = 5, // depends on a old known previus frame
|
||||
kVideoFrameAltRef = 6
|
||||
};
|
||||
|
||||
// Used to indicate which decode with errors mode should be used.
|
||||
enum SrsRtpDecodeErrorMode {
|
||||
kNoErrors, // Never decode with errors. Video will freeze
|
||||
// if nack is disabled.
|
||||
kSelectiveErrors, // Frames that are determined decodable in
|
||||
// VCMSessionInfo may be decoded with missing
|
||||
// packets. As not all incomplete frames will be
|
||||
// decodable, video will freeze if nack is disabled.
|
||||
kWithErrors // Release frames as needed. Errors may be
|
||||
// introduced as some encoded frames may not be
|
||||
// complete.
|
||||
};
|
||||
|
||||
// Used to estimate rolling average of packets per frame.
|
||||
static const float kFastConvergeMultiplier = 0.4f;
|
||||
static const float kNormalConvergeMultiplier = 0.2f;
|
||||
|
||||
enum { kMaxNumberOfFrames = 300 };
|
||||
enum { kStartNumberOfFrames = 6 };
|
||||
enum { kMaxVideoDelayMs = 10000 };
|
||||
enum { kPacketsPerFrameMultiplier = 5 };
|
||||
enum { kFastConvergeThreshold = 5};
|
||||
|
||||
enum SrsRtpJitterBufferEnum {
|
||||
kMaxConsecutiveOldFrames = 60,
|
||||
kMaxConsecutiveOldPackets = 300,
|
||||
kMaxPacketsInSession = 800,
|
||||
kBufferIncStepSizeBytes = 30000, // >20 packets.
|
||||
kMaxJBFrameSizeBytes = 4000000 // sanity don't go above 4Mbyte.
|
||||
};
|
||||
|
||||
enum SrsRtpFrameBufferEnum {
|
||||
kOutOfBoundsPacket = -7,
|
||||
kNotInitialized = -6,
|
||||
kOldPacket = -5,
|
||||
kGeneralError = -4,
|
||||
kFlushIndicator = -3, // Indicator that a flush has occurred.
|
||||
kTimeStampError = -2,
|
||||
kSizeError = -1,
|
||||
kNoError = 0,
|
||||
kIncomplete = 1, // Frame incomplete.
|
||||
kCompleteSession = 3, // at least one layer in the frame complete.
|
||||
kDecodableSession = 4, // Frame incomplete, but ready to be decoded
|
||||
kDuplicatePacket = 5 // We're receiving a duplicate packet.
|
||||
};
|
||||
|
||||
enum SrsRtpFrameBufferStateEnum {
|
||||
kStateEmpty, // frame popped by the RTP receiver
|
||||
kStateIncomplete, // frame that have one or more packet(s) stored
|
||||
kStateComplete, // frame that have all packets
|
||||
kStateDecodable // Hybrid mode - frame can be decoded
|
||||
};
|
||||
|
||||
enum SrsRtpNackMode {
|
||||
kNack,
|
||||
kNoNack
|
||||
};
|
||||
|
||||
// Used to indicate if a received packet contain a complete NALU (or equivalent)
|
||||
enum VCMNaluCompleteness {
|
||||
kNaluUnset = 0, // Packet has not been filled.
|
||||
kNaluComplete = 1, // Packet can be decoded as is.
|
||||
kNaluStart, // Packet contain beginning of NALU
|
||||
kNaluIncomplete, // Packet is not beginning or end of NALU
|
||||
kNaluEnd, // Packet is the end of a NALU
|
||||
};
|
||||
|
||||
enum RtpVideoCodecTypes {
|
||||
kRtpVideoNone,
|
||||
kRtpVideoGeneric,
|
||||
kRtpVideoVp8,
|
||||
kRtpVideoVp9,
|
||||
kRtpVideoH264,
|
||||
kRtpVideoPS
|
||||
};
|
||||
|
||||
|
||||
// Video codec types
|
||||
enum VideoCodecType {
|
||||
kVideoCodecVP8,
|
||||
kVideoCodecVP9,
|
||||
kVideoCodecH264,
|
||||
kVideoCodecH264SVC,
|
||||
kVideoCodecI420,
|
||||
kVideoCodecRED,
|
||||
kVideoCodecULPFEC,
|
||||
kVideoCodecGeneric,
|
||||
kVideoCodecH264PS,
|
||||
kVideoCodecUnknown
|
||||
};
|
||||
|
||||
// The packetization types that we support: single, aggregated, and fragmented.
|
||||
enum H264PacketizationTypes {
|
||||
kH264SingleNalu, // This packet contains a single NAL unit.
|
||||
kH264StapA, // This packet contains STAP-A (single time
|
||||
// aggregation) packets. If this packet has an
|
||||
// associated NAL unit type, it'll be for the
|
||||
// first such aggregated packet.
|
||||
kH264FuA, // This packet contains a FU-A (fragmentation
|
||||
// unit) packet, meaning it is a part of a frame
|
||||
// that was too large to fit into a single packet.
|
||||
};
|
||||
|
||||
enum { kH264StartCodeLengthBytes = 4};
|
||||
|
||||
// Used to pass data from jitter buffer to session info.
|
||||
// This data is then used in determining whether a frame is decodable.
|
||||
struct FrameData {
|
||||
int64_t rtt_ms;
|
||||
float rolling_average_packets_per_frame;
|
||||
};
|
||||
|
||||
inline bool IsNewerSequenceNumber(uint16_t sequence_number,
|
||||
uint16_t prev_sequence_number)
|
||||
{
|
||||
return sequence_number != prev_sequence_number &&
|
||||
static_cast<uint16_t>(sequence_number - prev_sequence_number) < 0x8000;
|
||||
}
|
||||
|
||||
inline bool IsNewerTimestamp(uint32_t timestamp, uint32_t prev_timestamp)
|
||||
{
|
||||
return timestamp != prev_timestamp &&
|
||||
static_cast<uint32_t>(timestamp - prev_timestamp) < 0x80000000;
|
||||
}
|
||||
|
||||
inline uint16_t LatestSequenceNumber(uint16_t sequence_number1,
|
||||
uint16_t sequence_number2)
|
||||
{
|
||||
return IsNewerSequenceNumber(sequence_number1, sequence_number2)
|
||||
? sequence_number1
|
||||
: sequence_number2;
|
||||
}
|
||||
|
||||
inline uint32_t LatestTimestamp(uint32_t timestamp1, uint32_t timestamp2)
|
||||
{
|
||||
return IsNewerTimestamp(timestamp1, timestamp2) ? timestamp1 : timestamp2;
|
||||
}
|
||||
|
||||
typedef std::list<SrsRtpFrameBuffer*> UnorderedFrameList;
|
||||
|
||||
class TimestampLessThan {
|
||||
public:
|
||||
bool operator() (const uint32_t& timestamp1,
|
||||
const uint32_t& timestamp2) const
|
||||
{
|
||||
return IsNewerTimestamp(timestamp2, timestamp1);
|
||||
}
|
||||
};
|
||||
|
||||
class FrameList
|
||||
: public std::map<uint32_t, SrsRtpFrameBuffer*, TimestampLessThan> {
|
||||
public:
|
||||
void InsertFrame(SrsRtpFrameBuffer* frame);
|
||||
SrsRtpFrameBuffer* PopFrame(uint32_t timestamp);
|
||||
SrsRtpFrameBuffer* Front() const;
|
||||
SrsRtpFrameBuffer* FrontNext() const;
|
||||
SrsRtpFrameBuffer* Back() const;
|
||||
int RecycleFramesUntilKeyFrame(FrameList::iterator* key_frame_it,
|
||||
UnorderedFrameList* free_frames);
|
||||
void CleanUpOldOrEmptyFrames(SrsRtpDecodingState* decoding_state, UnorderedFrameList* free_frames);
|
||||
void Reset(UnorderedFrameList* free_frames);
|
||||
};
|
||||
|
||||
|
||||
class VCMPacket {
|
||||
public:
|
||||
VCMPacket();
|
||||
VCMPacket(const uint8_t* ptr,
|
||||
size_t size,
|
||||
uint16_t seqNum,
|
||||
uint32_t timestamp,
|
||||
bool markerBit,
|
||||
H264PacketizationTypes type,
|
||||
RtpVideoCodecTypes rtpType,
|
||||
bool singlenual,
|
||||
bool isfirst,
|
||||
FrameType ftype
|
||||
);
|
||||
|
||||
void Reset();
|
||||
|
||||
uint8_t payloadType;
|
||||
uint32_t timestamp;
|
||||
// NTP time of the capture time in local timebase in milliseconds.
|
||||
int64_t ntp_time_ms_;
|
||||
uint16_t seqNum;
|
||||
const uint8_t* dataPtr;
|
||||
size_t sizeBytes;
|
||||
bool markerBit;
|
||||
|
||||
FrameType frameType;
|
||||
VideoCodecType codec;
|
||||
|
||||
bool isFirstPacket; // Is this first packet in a frame.
|
||||
VCMNaluCompleteness completeNALU; // Default is kNaluIncomplete.
|
||||
bool insertStartCode; // True if a start code should be inserted before this
|
||||
// packet.
|
||||
int width;
|
||||
int height;
|
||||
//RTPVideoHeader codecSpecificHeader;
|
||||
|
||||
|
||||
//H264 header
|
||||
H264PacketizationTypes h264packetizationType;
|
||||
bool h264singleNalu;
|
||||
|
||||
public:
|
||||
void CopyCodecSpecifics(RtpVideoCodecTypes codecType, bool H264single_nalu, bool firstPacket);
|
||||
};
|
||||
|
||||
class SrsRtpFrameBuffer {
|
||||
public:
|
||||
SrsRtpFrameBuffer();
|
||||
virtual ~SrsRtpFrameBuffer();
|
||||
|
||||
public:
|
||||
SrsRtpFrameBufferEnum InsertPacket(const VCMPacket& packet, const FrameData& frame_data);
|
||||
void UpdateCompleteSession();
|
||||
void UpdateDecodableSession(const FrameData& frame_data);
|
||||
bool HaveFirstPacket() const;
|
||||
bool HaveLastPacket() const;
|
||||
void Reset();
|
||||
|
||||
uint32_t GetTimeStamp() const;
|
||||
FrameType GetFrameType() const;
|
||||
SrsRtpFrameBufferStateEnum GetState() const;
|
||||
|
||||
int32_t GetHighSeqNum() const;
|
||||
int32_t GetLowSeqNum() const;
|
||||
size_t Length() const;
|
||||
const uint8_t* Buffer() const;
|
||||
|
||||
int NumPackets() const;
|
||||
void InformOfEmptyPacket(uint16_t seq_num);
|
||||
|
||||
bool complete() const;
|
||||
bool decodable() const;
|
||||
|
||||
bool DeletePacket(int &count);
|
||||
void PrepareForDecode(bool continuous);
|
||||
|
||||
private:
|
||||
|
||||
typedef std::list<VCMPacket> PacketList;
|
||||
typedef PacketList::iterator PacketIterator;
|
||||
typedef PacketList::const_iterator PacketIteratorConst;
|
||||
typedef PacketList::reverse_iterator ReversePacketIterator;
|
||||
|
||||
bool InSequence(const PacketIterator& packet_it,
|
||||
const PacketIterator& prev_packet_it);
|
||||
|
||||
size_t InsertBuffer(uint8_t* frame_buffer, PacketIterator packet_it);
|
||||
size_t Insert(const uint8_t* buffer, size_t length, bool insert_start_code, uint8_t* frame_buffer);
|
||||
void ShiftSubsequentPackets(PacketIterator it, int steps_to_shift);
|
||||
void VerifyAndAllocate(const uint32_t minimumSize);
|
||||
void UpdateDataPointers(const uint8_t* old_base_ptr, const uint8_t* new_base_ptr);
|
||||
size_t DeletePacketData(PacketIterator start, PacketIterator end);
|
||||
size_t MakeDecodable();
|
||||
|
||||
|
||||
PacketList packets_;
|
||||
int empty_seq_num_low_;
|
||||
int empty_seq_num_high_;
|
||||
|
||||
int first_packet_seq_num_;
|
||||
int last_packet_seq_num_;
|
||||
|
||||
bool complete_;
|
||||
bool decodable_;
|
||||
|
||||
uint32_t timeStamp_;
|
||||
FrameType frame_type_;
|
||||
|
||||
SrsRtpDecodeErrorMode decode_error_mode_;
|
||||
SrsRtpFrameBufferStateEnum state_;
|
||||
|
||||
//uint16_t nackCount_;
|
||||
//int64_t latestPacketTimeMs_;
|
||||
|
||||
// The payload.
|
||||
uint8_t* _buffer;
|
||||
size_t _size;
|
||||
size_t _length;
|
||||
};
|
||||
|
||||
class SrsRtpDecodingState {
|
||||
public:
|
||||
SrsRtpDecodingState();
|
||||
~SrsRtpDecodingState();
|
||||
// Check for old frame
|
||||
bool IsOldFrame(const SrsRtpFrameBuffer* frame) const;
|
||||
// Check for old packet
|
||||
bool IsOldPacket(const VCMPacket* packet);
|
||||
// Check for frame continuity based on current decoded state. Use best method
|
||||
// possible, i.e. temporal info, picture ID or sequence number.
|
||||
bool ContinuousFrame(const SrsRtpFrameBuffer* frame) const;
|
||||
void SetState(const SrsRtpFrameBuffer* frame);
|
||||
void CopyFrom(const SrsRtpDecodingState& state);
|
||||
bool UpdateEmptyFrame(const SrsRtpFrameBuffer* frame);
|
||||
// Update the sequence number if the timestamp matches current state and the
|
||||
// sequence number is higher than the current one. This accounts for packets
|
||||
// arriving late.
|
||||
void UpdateOldPacket(const VCMPacket* packet);
|
||||
void SetSeqNum(uint16_t new_seq_num);
|
||||
void Reset();
|
||||
uint32_t time_stamp() const;
|
||||
uint16_t sequence_num() const;
|
||||
// Return true if at initial state.
|
||||
bool in_initial_state() const;
|
||||
// Return true when sync is on - decode all layers.
|
||||
bool full_sync() const;
|
||||
|
||||
private:
|
||||
void UpdateSyncState(const SrsRtpFrameBuffer* frame);
|
||||
// Designated continuity functions
|
||||
//bool ContinuousPictureId(int picture_id) const;
|
||||
bool ContinuousSeqNum(uint16_t seq_num) const;
|
||||
//bool ContinuousLayer(int temporal_id, int tl0_pic_id) const;
|
||||
//bool UsingPictureId(const SrsRtpFrameBuffer* frame) const;
|
||||
|
||||
// Keep state of last decoded frame.
|
||||
// TODO(mikhal/stefan): create designated classes to handle these types.
|
||||
uint16_t sequence_num_;
|
||||
uint32_t time_stamp_;
|
||||
bool full_sync_; // Sync flag when temporal layers are used.
|
||||
bool in_initial_state_;
|
||||
|
||||
bool m_firstPacket;
|
||||
};
|
||||
|
||||
// The time jitter correct for rtp.
|
||||
class SrsRtpTimeJitter
|
||||
{
|
||||
private:
|
||||
int64_t previous_timestamp;
|
||||
int64_t pts;
|
||||
int delta;
|
||||
public:
|
||||
SrsRtpTimeJitter();
|
||||
virtual ~SrsRtpTimeJitter();
|
||||
public:
|
||||
int64_t timestamp();
|
||||
srs_error_t correct(int64_t& ts);
|
||||
void reset();
|
||||
};
|
||||
|
||||
class SrsRtpJitterBuffer
|
||||
{
|
||||
public:
|
||||
SrsRtpJitterBuffer(std::string key);
|
||||
virtual ~SrsRtpJitterBuffer();
|
||||
|
||||
public:
|
||||
srs_error_t start();
|
||||
void Reset();
|
||||
SrsRtpFrameBufferEnum InsertPacket(uint16_t seq, uint32_t ts, bool maker, char *buf, int size,
|
||||
bool* retransmitted);
|
||||
void ReleaseFrame(SrsRtpFrameBuffer* frame);
|
||||
bool FoundFrame(uint32_t& time_stamp);
|
||||
bool GetFrame(char **buffer, int &buf_len, int &size, bool &keyframe, const uint32_t time_stamp);
|
||||
void SetDecodeErrorMode(SrsRtpDecodeErrorMode error_mode);
|
||||
void SetNackMode(SrsRtpNackMode mode,int64_t low_rtt_nack_threshold_ms,
|
||||
int64_t high_rtt_nack_threshold_ms);
|
||||
void SetNackSettings(size_t max_nack_list_size,int max_packet_age_to_nack,
|
||||
int max_incomplete_time_ms);
|
||||
uint16_t* GetNackList(uint16_t* nack_list_size, bool* request_key_frame);
|
||||
void Flush();
|
||||
void ResetJittter();
|
||||
|
||||
bool isFirstKeyFrame;
|
||||
private:
|
||||
|
||||
SrsRtpFrameBufferEnum GetFrameByRtpPacket(const VCMPacket& packet, SrsRtpFrameBuffer** frame,
|
||||
FrameList** frame_list);
|
||||
SrsRtpFrameBuffer* GetEmptyFrame();
|
||||
bool NextCompleteTimestamp(uint32_t max_wait_time_ms, uint32_t* timestamp);
|
||||
bool NextMaybeIncompleteTimestamp(uint32_t* timestamp);
|
||||
SrsRtpFrameBuffer* ExtractAndSetDecode(uint32_t timestamp);
|
||||
SrsRtpFrameBuffer* NextFrame() const;
|
||||
|
||||
|
||||
bool TryToIncreaseJitterBufferSize();
|
||||
bool RecycleFramesUntilKeyFrame();
|
||||
bool IsContinuous(const SrsRtpFrameBuffer& frame) const;
|
||||
bool IsContinuousInState(const SrsRtpFrameBuffer& frame,
|
||||
const SrsRtpDecodingState& decoding_state) const;
|
||||
void FindAndInsertContinuousFrames(const SrsRtpFrameBuffer& new_frame);
|
||||
void CleanUpOldOrEmptyFrames();
|
||||
|
||||
//nack
|
||||
bool UpdateNackList(uint16_t sequence_number);
|
||||
bool TooLargeNackList() const;
|
||||
bool HandleTooLargeNackList();
|
||||
bool MissingTooOldPacket(uint16_t latest_sequence_number) const;
|
||||
bool HandleTooOldPackets(uint16_t latest_sequence_number);
|
||||
void DropPacketsFromNackList(uint16_t last_decoded_sequence_number);
|
||||
SrsRtpNackMode nack_mode() const;
|
||||
int NonContinuousOrIncompleteDuration();
|
||||
uint16_t EstimatedLowSequenceNumber(const SrsRtpFrameBuffer& frame) const;
|
||||
bool WaitForRetransmissions();
|
||||
|
||||
bool IsPacketInOrder(uint16_t sequence_number);
|
||||
bool IsFirstPacketInFrame(uint32_t ts, uint16_t seq);
|
||||
|
||||
private:
|
||||
class SequenceNumberLessThan {
|
||||
public:
|
||||
bool operator() (const uint16_t& sequence_number1,
|
||||
const uint16_t& sequence_number2) const
|
||||
{
|
||||
return IsNewerSequenceNumber(sequence_number2, sequence_number1);
|
||||
}
|
||||
};
|
||||
typedef std::set<uint16_t, SequenceNumberLessThan> SequenceNumberSet;
|
||||
|
||||
std::string key_;
|
||||
|
||||
srs_cond_t wait_cond_t;
|
||||
// If we are running (have started) or not.
|
||||
bool running_;
|
||||
// Number of allocated frames.
|
||||
int max_number_of_frames_;
|
||||
UnorderedFrameList free_frames_;
|
||||
FrameList decodable_frames_;
|
||||
FrameList incomplete_frames_;
|
||||
SrsRtpDecodingState last_decoded_state_;
|
||||
bool first_packet_since_reset_;
|
||||
|
||||
// Statistics.
|
||||
//VCMReceiveStatisticsCallback* stats_callback_ GUARDED_BY(crit_sect_);
|
||||
// Frame counts for each type (key, delta, ...)
|
||||
//FrameCounts receive_statistics_;
|
||||
// Latest calculated frame rates of incoming stream.
|
||||
unsigned int incoming_frame_rate_;
|
||||
unsigned int incoming_frame_count_;
|
||||
int64_t time_last_incoming_frame_count_;
|
||||
unsigned int incoming_bit_count_;
|
||||
unsigned int incoming_bit_rate_;
|
||||
// Number of frames in a row that have been too old.
|
||||
int num_consecutive_old_frames_;
|
||||
// Number of packets in a row that have been too old.
|
||||
int num_consecutive_old_packets_;
|
||||
// Number of packets received.
|
||||
int num_packets_;
|
||||
int num_packets_free_;
|
||||
// Number of duplicated packets received.
|
||||
int num_duplicated_packets_;
|
||||
// Number of packets discarded by the jitter buffer.
|
||||
int num_discarded_packets_;
|
||||
// Time when first packet is received.
|
||||
int64_t time_first_packet_ms_;
|
||||
|
||||
// Jitter estimation.
|
||||
// Filter for estimating jitter.
|
||||
//VCMJitterEstimator jitter_estimate_;
|
||||
// Calculates network delays used for jitter calculations.
|
||||
//VCMInterFrameDelay inter_frame_delay_;
|
||||
//VCMJitterSample waiting_for_completion_;
|
||||
int64_t rtt_ms_;
|
||||
|
||||
// NACK and retransmissions.
|
||||
SrsRtpNackMode nack_mode_;
|
||||
int64_t low_rtt_nack_threshold_ms_;
|
||||
int64_t high_rtt_nack_threshold_ms_;
|
||||
// Holds the internal NACK list (the missing sequence numbers).
|
||||
SequenceNumberSet missing_sequence_numbers_;
|
||||
uint16_t latest_received_sequence_number_;
|
||||
std::vector<uint16_t> nack_seq_nums_;
|
||||
size_t max_nack_list_size_;
|
||||
int max_packet_age_to_nack_; // Measured in sequence numbers.
|
||||
int max_incomplete_time_ms_;
|
||||
|
||||
SrsRtpDecodeErrorMode decode_error_mode_;
|
||||
// Estimated rolling average of packets per frame
|
||||
float average_packets_per_frame_;
|
||||
// average_packets_per_frame converges fast if we have fewer than this many
|
||||
// frames.
|
||||
int frame_counter_;
|
||||
|
||||
uint32_t last_received_timestamp_;
|
||||
uint16_t last_received_sequence_number_;
|
||||
bool first_packet_;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,206 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2013-2021 Lixin
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#ifndef SRS_APP_GB28181_SIP_HPP
|
||||
#define SRS_APP_GB28181_SIP_HPP
|
||||
|
||||
#include <srs_core.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include <srs_app_log.hpp>
|
||||
#include <srs_app_gb28181_stack.hpp>
|
||||
#include <srs_app_gb28181.hpp>
|
||||
#include <srs_app_pithy_print.hpp>
|
||||
#include <srs_service_conn.hpp>
|
||||
|
||||
class SrsConfDirective;
|
||||
class SrsSipRequest;
|
||||
class SrsGb28181Config;
|
||||
class SrsSipStack;
|
||||
class SrsGb28181SipService;
|
||||
class SrsGb28181Device;
|
||||
|
||||
enum SrsGb28181SipSessionStatusType{
|
||||
SrsGb28181SipSessionUnkonw = 0,
|
||||
SrsGb28181SipSessionRegisterOk = 1,
|
||||
SrsGb28181SipSessionAliveOk = 2,
|
||||
SrsGb28181SipSessionInviteOk = 3,
|
||||
SrsGb28181SipSessionTrying = 4,
|
||||
SrsGb28181SipSessionBye = 5,
|
||||
};
|
||||
|
||||
class SrsGb28181Device
|
||||
{
|
||||
public:
|
||||
SrsGb28181Device();
|
||||
virtual ~SrsGb28181Device();
|
||||
public:
|
||||
std::string device_id;
|
||||
std::string device_name;
|
||||
std::string device_status;
|
||||
SrsGb28181SipSessionStatusType invite_status;
|
||||
srs_utime_t invite_time;
|
||||
SrsSipRequest req_inivate;
|
||||
};
|
||||
|
||||
class SrsGb28181SipSession: public ISrsCoroutineHandler, public ISrsConnection
|
||||
{
|
||||
private:
|
||||
//SrsSipRequest *req;
|
||||
SrsGb28181SipService *servcie;
|
||||
std::string _session_id;
|
||||
SrsCoroutine* trd;
|
||||
SrsPithyPrint* pprint;
|
||||
private:
|
||||
SrsGb28181SipSessionStatusType _register_status;
|
||||
SrsGb28181SipSessionStatusType _alive_status;
|
||||
SrsGb28181SipSessionStatusType _invite_status;
|
||||
srs_utime_t _register_time;
|
||||
srs_utime_t _alive_time;
|
||||
srs_utime_t _invite_time;
|
||||
srs_utime_t _reg_expires;
|
||||
srs_utime_t _query_catalog_time;
|
||||
|
||||
std::string _peer_ip;
|
||||
int _peer_port;
|
||||
|
||||
sockaddr _from;
|
||||
int _fromlen;
|
||||
SrsSipRequest *req;
|
||||
|
||||
std::map<std::string, SrsGb28181Device*> _device_list;
|
||||
//std::map<std::string, int> _device_status;
|
||||
int _sip_cseq;
|
||||
|
||||
public:
|
||||
SrsGb28181SipSession(SrsGb28181SipService *c, SrsSipRequest* r);
|
||||
virtual ~SrsGb28181SipSession();
|
||||
|
||||
private:
|
||||
void destroy();
|
||||
|
||||
public:
|
||||
void set_register_status(SrsGb28181SipSessionStatusType s) { _register_status = s;}
|
||||
void set_alive_status(SrsGb28181SipSessionStatusType s) { _alive_status = s;}
|
||||
void set_invite_status(SrsGb28181SipSessionStatusType s) { _invite_status = s;}
|
||||
void set_register_time(srs_utime_t t) { _register_time = t;}
|
||||
void set_alive_time(srs_utime_t t) { _alive_time = t;}
|
||||
void set_invite_time(srs_utime_t t) { _invite_time = t;}
|
||||
//void set_recv_rtp_time(srs_utime_t t) { _recv_rtp_time = t;}
|
||||
void set_reg_expires(int e) { _reg_expires = e*SRS_UTIME_SECONDS;}
|
||||
void set_peer_ip(std::string i) { _peer_ip = i;}
|
||||
void set_peer_port(int o) { _peer_port = o;}
|
||||
void set_sockaddr(sockaddr f) { _from = f;}
|
||||
void set_sockaddr_len(int l) { _fromlen = l;}
|
||||
void set_request(SrsSipRequest *r) { req->copy(r);}
|
||||
|
||||
SrsGb28181SipSessionStatusType register_status() { return _register_status;}
|
||||
SrsGb28181SipSessionStatusType alive_status() { return _alive_status;}
|
||||
SrsGb28181SipSessionStatusType invite_status() { return _invite_status;}
|
||||
srs_utime_t register_time() { return _register_time;}
|
||||
srs_utime_t alive_time() { return _alive_time;}
|
||||
srs_utime_t invite_time() { return _invite_time;}
|
||||
//srs_utime_t recv_rtp_time() { return _recv_rtp_time;}
|
||||
int reg_expires() { return _reg_expires;}
|
||||
std::string peer_ip() { return _peer_ip;}
|
||||
int peer_port() { return _peer_port;}
|
||||
sockaddr sockaddr_from() { return _from;}
|
||||
int sockaddr_fromlen() { return _fromlen;}
|
||||
SrsSipRequest request() { return *req;}
|
||||
int sip_cseq(){ return _sip_cseq++;}
|
||||
|
||||
std::string session_id() { return _session_id;}
|
||||
std::map<std::string, std::map<std::string, std::string> > item_list;
|
||||
int item_list_sumnum;
|
||||
public:
|
||||
void update_device_list(std::map<std::string, std::string> devlist);
|
||||
void clear_device_list();
|
||||
SrsGb28181Device *get_device_info(std::string chid);
|
||||
void dumps(SrsJsonObject* obj);
|
||||
void dumpItemList(SrsJsonObject* obj);
|
||||
|
||||
public:
|
||||
virtual srs_error_t serve();
|
||||
|
||||
// Interface ISrsOneCycleThreadHandler
|
||||
public:
|
||||
virtual srs_error_t cycle();
|
||||
// Interface ISrsConnection.
|
||||
public:
|
||||
virtual std::string remote_ip();
|
||||
virtual const SrsContextId& get_id();
|
||||
virtual std::string desc();
|
||||
private:
|
||||
virtual srs_error_t do_cycle();
|
||||
};
|
||||
|
||||
class SrsGb28181SipService : public ISrsUdpHandler
|
||||
{
|
||||
private:
|
||||
SrsSipStack *sip;
|
||||
SrsGb28181Config *config;
|
||||
srs_netfd_t lfd;
|
||||
|
||||
std::map<std::string, SrsGb28181SipSession*> sessions;
|
||||
std::map<std::string, SrsGb28181SipSession*> sessions_by_callid;
|
||||
|
||||
srs_mutex_t lock_session;
|
||||
public:
|
||||
SrsGb28181SipService(SrsConfDirective* c);
|
||||
virtual ~SrsGb28181SipService();
|
||||
|
||||
// Interface ISrsUdpHandler
|
||||
public:
|
||||
virtual srs_error_t on_udp_packet(const sockaddr* from, const int fromlen, char* buf, int nb_buf);
|
||||
virtual void set_stfd(srs_netfd_t fd);
|
||||
private:
|
||||
void destroy();
|
||||
srs_error_t on_udp_sip(std::string host, int port, std::string recv_msg, sockaddr* from, int fromlen);
|
||||
public:
|
||||
int send_message(sockaddr* f, int l, std::stringstream& ss);
|
||||
|
||||
int send_ack(SrsSipRequest *req, sockaddr *f, int l);
|
||||
int send_status(SrsSipRequest *req, sockaddr *f, int l);
|
||||
|
||||
srs_error_t send_invite(SrsSipRequest *req, std::string ip, int port, uint32_t ssrc, std::string chid);
|
||||
srs_error_t send_bye(SrsSipRequest *req, std::string chid);
|
||||
srs_error_t send_query_catalog(SrsSipRequest *req);
|
||||
srs_error_t send_ptz(SrsSipRequest *req, std::string chid, std::string cmd, uint8_t speed, int priority);
|
||||
|
||||
// The SIP command is transmitted through HTTP API,
|
||||
// and the body content is transmitted to the device,
|
||||
// mainly for testing and debugging, For example, here is HTTP body:
|
||||
// BYE sip:34020000001320000003@3402000000 SIP/2.0
|
||||
// Via: SIP/2.0/UDP 39.100.155.146:15063;rport;branch=z9hG4bK34205410
|
||||
// From: <sip:34020000002000000001@3402000000>;tag=512355410
|
||||
// To: <sip:34020000001320000003@3402000000>;tag=680367414
|
||||
// Call-ID: 200003304
|
||||
// CSeq: 21 BYE
|
||||
// Max-Forwards: 70
|
||||
// User-Agent: SRS/4.0.4(Leo)
|
||||
// Content-Length: 0
|
||||
//
|
||||
//
|
||||
srs_error_t send_sip_raw_data(SrsSipRequest *req, std::string data);
|
||||
srs_error_t query_sip_session(std::string sid, SrsJsonArray* arr);
|
||||
srs_error_t query_device_list(std::string sid, SrsJsonArray* arr);
|
||||
|
||||
public:
|
||||
srs_error_t fetch_or_create_sip_session(SrsSipRequest *req, SrsGb28181SipSession** sess);
|
||||
SrsGb28181SipSession* fetch(std::string id);
|
||||
void remove_session(std::string id);
|
||||
SrsGb28181Config* get_config();
|
||||
|
||||
void sip_session_map_by_callid(SrsGb28181SipSession *sess, std::string call_id);
|
||||
void sip_session_unmap_by_callid(std::string call_id);
|
||||
SrsGb28181SipSession* fetch_session_by_callid(std::string call_id);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,168 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2013-2021 Lixin
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#ifndef SRS_APP_GB28181_STACK_HPP
|
||||
#define SRS_APP_GB28181_STACK_HPP
|
||||
|
||||
#include <srs_core.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include <srs_kernel_consts.hpp>
|
||||
#include <srs_rtsp_stack.hpp>
|
||||
|
||||
class SrsBuffer;
|
||||
class SrsSimpleStream;
|
||||
class SrsAudioFrame;
|
||||
|
||||
// SIP methods
|
||||
#define SRS_SIP_METHOD_REGISTER "REGISTER"
|
||||
#define SRS_SIP_METHOD_MESSAGE "MESSAGE"
|
||||
#define SRS_SIP_METHOD_INVITE "INVITE"
|
||||
#define SRS_SIP_METHOD_ACK "ACK"
|
||||
#define SRS_SIP_METHOD_BYE "BYE"
|
||||
|
||||
// SIP-Version
|
||||
#define SRS_SIP_VERSION "SIP/2.0"
|
||||
#define SRS_SIP_USER_AGENT RTMP_SIG_SRS_SERVER
|
||||
|
||||
#define SRS_SIP_PTZ_START 0xA5
|
||||
|
||||
|
||||
enum SrsSipCmdType{
|
||||
SrsSipCmdRequest=0,
|
||||
SrsSipCmdRespone=1
|
||||
};
|
||||
|
||||
enum SrsSipPtzCmdType{
|
||||
SrsSipPtzCmdStop = 0x00,
|
||||
SrsSipPtzCmdRight = 0x01,
|
||||
SrsSipPtzCmdLeft = 0x02,
|
||||
SrsSipPtzCmdDown = 0x04,
|
||||
SrsSipPtzCmdUp = 0x08,
|
||||
SrsSipPtzCmdZoomIn = 0x10,
|
||||
SrsSipPtzCmdZoomOut = 0x20
|
||||
};
|
||||
|
||||
std::string srs_sip_get_utc_date();
|
||||
|
||||
class SrsSipRequest
|
||||
{
|
||||
public:
|
||||
//sip header member
|
||||
std::string method;
|
||||
std::string uri;
|
||||
std::string version;
|
||||
std::string status;
|
||||
|
||||
std::string via;
|
||||
std::string from;
|
||||
std::string to;
|
||||
std::string from_tag;
|
||||
std::string to_tag;
|
||||
std::string branch;
|
||||
|
||||
std::string call_id;
|
||||
long seq;
|
||||
|
||||
std::string contact;
|
||||
std::string user_agent;
|
||||
|
||||
std::string content_type;
|
||||
long content_length;
|
||||
|
||||
long expires;
|
||||
int max_forwards;
|
||||
|
||||
std::string www_authenticate;
|
||||
std::string authorization;
|
||||
|
||||
std::string chid;
|
||||
|
||||
std::map<std::string, std::string> xml_body_map;
|
||||
std::map<std::string, std::string> device_list_map;
|
||||
// add an item_list, you can do a lot of other things
|
||||
// used by DeviceList, Alarmstatus, RecordList in "GB/T 28181—2016"
|
||||
std::vector<std::map<std::string, std::string> > item_list;
|
||||
|
||||
public:
|
||||
std::string serial;
|
||||
std::string realm;
|
||||
std::string sip_auth_id;
|
||||
std::string sip_auth_pwd;
|
||||
std::string sip_username;
|
||||
std::string peer_ip;
|
||||
int peer_port;
|
||||
std::string host;
|
||||
int host_port;
|
||||
SrsSipCmdType cmdtype;
|
||||
|
||||
std::string from_realm;
|
||||
std::string to_realm;
|
||||
uint32_t y_ssrc;
|
||||
|
||||
public:
|
||||
SrsRtspSdp* sdp;
|
||||
SrsRtspTransport* transport;
|
||||
public:
|
||||
SrsSipRequest();
|
||||
virtual ~SrsSipRequest();
|
||||
public:
|
||||
virtual bool is_register();
|
||||
virtual bool is_invite();
|
||||
virtual bool is_message();
|
||||
virtual bool is_ack();
|
||||
virtual bool is_bye();
|
||||
|
||||
virtual void copy(SrsSipRequest* src);
|
||||
public:
|
||||
virtual std::string get_cmdtype_str();
|
||||
};
|
||||
|
||||
// The gb28181 sip protocol stack.
|
||||
class SrsSipStack
|
||||
{
|
||||
private:
|
||||
// The cached bytes buffer.
|
||||
SrsSimpleStream* buf;
|
||||
public:
|
||||
SrsSipStack();
|
||||
virtual ~SrsSipStack();
|
||||
public:
|
||||
virtual srs_error_t parse_request(SrsSipRequest** preq, const char *recv_msg, int nb_buf);
|
||||
protected:
|
||||
virtual srs_error_t do_parse_request(SrsSipRequest* req, const char *recv_msg);
|
||||
virtual srs_error_t parse_xml(std::string xml_msg, std::map<std::string, std::string> &json_map, std::vector<std::map<std::string, std::string> > &item_list);
|
||||
|
||||
private:
|
||||
//response from
|
||||
virtual std::string get_sip_from(SrsSipRequest const *req);
|
||||
//response to
|
||||
virtual std::string get_sip_to(SrsSipRequest const *req);
|
||||
//response via
|
||||
virtual std::string get_sip_via(SrsSipRequest const *req);
|
||||
|
||||
public:
|
||||
//response: request sent by the sip-agent, wait for sip-server response
|
||||
virtual void resp_status(std::stringstream& ss, SrsSipRequest *req);
|
||||
virtual void resp_keepalive(std::stringstream& ss, SrsSipRequest *req);
|
||||
|
||||
//request: request sent by the sip-server, wait for sip-agent response
|
||||
virtual void req_invite(std::stringstream& ss, SrsSipRequest *req, std::string ip,
|
||||
int port, uint32_t ssrc, bool tcpFlag);
|
||||
virtual void req_ack(std::stringstream& ss, SrsSipRequest *req);
|
||||
virtual void req_bye(std::stringstream& ss, SrsSipRequest *req);
|
||||
virtual void req_401_unauthorized(std::stringstream& ss, SrsSipRequest *req);
|
||||
virtual void req_query_catalog(std::stringstream& ss, SrsSipRequest *req);
|
||||
virtual void req_ptz(std::stringstream& ss, SrsSipRequest *req, uint8_t cmd, uint8_t speed, int priority);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue