Create Runner class
Several classes have common active_ and runner_ variables and stop/start/active routines (such as reader and dispatch). Create one common class for these to make the interface cleaner
This commit is contained in:
parent
bde19e3f7f
commit
0f0a052e54
|
|
@ -50,7 +50,7 @@ kvz_rtp::connection::connection(rtp_format_t fmt, bool reader):
|
|||
kvz_rtp::connection::~connection()
|
||||
{
|
||||
if (rtcp_) {
|
||||
rtcp_->terminate();
|
||||
rtcp_->stop();
|
||||
delete rtcp_;
|
||||
}
|
||||
|
||||
|
|
|
|||
157
src/conn.hh
157
src/conn.hh
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include "frame.hh"
|
||||
#include "rtcp.hh"
|
||||
#include "runner.hh"
|
||||
#include "socket.hh"
|
||||
#include "util.hh"
|
||||
|
||||
|
|
@ -22,104 +23,102 @@ namespace kvz_rtp {
|
|||
class dispatcher;
|
||||
class frame_queue;
|
||||
|
||||
class connection {
|
||||
public:
|
||||
connection(rtp_format_t fmt, bool reader);
|
||||
virtual ~connection();
|
||||
class connection : public runner {
|
||||
public:
|
||||
connection(rtp_format_t fmt, bool reader);
|
||||
virtual ~connection();
|
||||
|
||||
virtual rtp_error_t start() = 0;
|
||||
uint16_t get_sequence() const;
|
||||
uint32_t get_ssrc() const;
|
||||
uint8_t get_payload() const;
|
||||
|
||||
uint16_t get_sequence() const;
|
||||
uint32_t get_ssrc() const;
|
||||
uint8_t get_payload() const;
|
||||
socket& get_socket();
|
||||
socket_t get_raw_socket();
|
||||
|
||||
socket& get_socket();
|
||||
socket_t get_raw_socket();
|
||||
void set_payload(rtp_format_t fmt);
|
||||
void set_ssrc(uint32_t ssrc);
|
||||
|
||||
void set_payload(rtp_format_t fmt);
|
||||
void set_ssrc(uint32_t ssrc);
|
||||
/* Functions for increasing various RTP statistics
|
||||
* Overloaded functions without parameters increase the counter by 1
|
||||
*
|
||||
* Functions that take SSRC are for updating receiver statistics */
|
||||
void inc_rtp_sequence(size_t n);
|
||||
void inc_sent_bytes(size_t n);
|
||||
void inc_sent_pkts(size_t n);
|
||||
void inc_sent_pkts();
|
||||
void inc_rtp_sequence();
|
||||
|
||||
/* Functions for increasing various RTP statistics
|
||||
* Overloaded functions without parameters increase the counter by 1
|
||||
*
|
||||
* Functions that take SSRC are for updating receiver statistics */
|
||||
void inc_rtp_sequence(size_t n);
|
||||
void inc_sent_bytes(size_t n);
|
||||
void inc_sent_pkts(size_t n);
|
||||
void inc_sent_pkts();
|
||||
void inc_rtp_sequence();
|
||||
/* See RTCP->update_receiver_stats() for documentation */
|
||||
rtp_error_t update_receiver_stats(kvz_rtp::frame::rtp_frame *frame);
|
||||
|
||||
/* See RTCP->update_receiver_stats() for documentation */
|
||||
rtp_error_t update_receiver_stats(kvz_rtp::frame::rtp_frame *frame);
|
||||
/* Config setters and getter, used f.ex. for Opus
|
||||
*
|
||||
* Return nullptr if the media doesn't have a config
|
||||
* Otherwise return void pointer to config (caller must do the cast) */
|
||||
void set_config(void *config);
|
||||
void *get_config();
|
||||
|
||||
/* Config setters and getter, used f.ex. for Opus
|
||||
*
|
||||
* Return nullptr if the media doesn't have a config
|
||||
* Otherwise return void pointer to config (caller must do the cast) */
|
||||
void set_config(void *config);
|
||||
void *get_config();
|
||||
/* helper function fill the rtp header to allocated buffer,
|
||||
* caller must make sure that the buffer is at least 12 bytes long */
|
||||
void fill_rtp_header(uint8_t *buffer);
|
||||
|
||||
/* helper function fill the rtp header to allocated buffer,
|
||||
* caller must make sure that the buffer is at least 12 bytes long */
|
||||
void fill_rtp_header(uint8_t *buffer);
|
||||
void update_rtp_sequence(uint8_t *buffer);
|
||||
|
||||
void update_rtp_sequence(uint8_t *buffer);
|
||||
/* Set clock rate for RTP timestamp in Hz
|
||||
* This must be set, otherwise the timestamps won't be correct */
|
||||
void set_clock_rate(uint32_t clock_rate);
|
||||
|
||||
/* Set clock rate for RTP timestamp in Hz
|
||||
* This must be set, otherwise the timestamps won't be correct */
|
||||
void set_clock_rate(uint32_t clock_rate);
|
||||
/* Create RTCP instance for this connection
|
||||
*
|
||||
* This instance listens to src_port for incoming RTCP reports and sends
|
||||
* repots about this session to dst_addr:dst_port every N seconds (see RFC 3550) */
|
||||
rtp_error_t create_rtcp(std::string dst_addr, int dst_port, int src_port);
|
||||
|
||||
/* Create RTCP instance for this connection
|
||||
*
|
||||
* This instance listens to src_port for incoming RTCP reports and sends
|
||||
* repots about this session to dst_addr:dst_port every N seconds (see RFC 3550) */
|
||||
rtp_error_t create_rtcp(std::string dst_addr, int dst_port, int src_port);
|
||||
/* Get pointer to frame queue
|
||||
*
|
||||
* Return pointer to frame queue for writers
|
||||
* Return nullptr for readers */
|
||||
kvz_rtp::frame_queue *get_frame_queue();
|
||||
|
||||
/* Get pointer to frame queue
|
||||
*
|
||||
* Return pointer to frame queue for writers
|
||||
* Return nullptr for readers */
|
||||
kvz_rtp::frame_queue *get_frame_queue();
|
||||
/* Get pointer to dispatcher
|
||||
*
|
||||
* Return pointer to dispatcher for medias that use dispatcher
|
||||
* Return nullptr otherwise */
|
||||
kvz_rtp::dispatcher *get_dispatcher();
|
||||
|
||||
/* Get pointer to dispatcher
|
||||
*
|
||||
* Return pointer to dispatcher for medias that use dispatcher
|
||||
* Return nullptr otherwise */
|
||||
kvz_rtp::dispatcher *get_dispatcher();
|
||||
/* Install deallocation hook for the transaction's data payload
|
||||
*
|
||||
* When SCD has finished processing the request,
|
||||
* in deinit_transaction(), it will calls this hook if it has been set. */
|
||||
void install_dealloc_hook(void (*dealloc_hook)(void *));
|
||||
|
||||
/* Install deallocation hook for the transaction's data payload
|
||||
*
|
||||
* When SCD has finished processing the request,
|
||||
* in deinit_transaction(), it will calls this hook if it has been set. */
|
||||
void install_dealloc_hook(void (*dealloc_hook)(void *));
|
||||
/* Return pointer to RTCP object if RTCP has been enabled
|
||||
* Otherwise return nullptr
|
||||
*
|
||||
* TODO make this const */
|
||||
kvz_rtp::rtcp *get_rtcp();
|
||||
|
||||
/* Return pointer to RTCP object if RTCP has been enabled
|
||||
* Otherwise return nullptr
|
||||
*
|
||||
* TODO make this const */
|
||||
kvz_rtp::rtcp *get_rtcp();
|
||||
protected:
|
||||
void *config_;
|
||||
uint32_t id_;
|
||||
|
||||
protected:
|
||||
void *config_;
|
||||
uint32_t id_;
|
||||
kvz_rtp::socket socket_;
|
||||
kvz_rtp::rtcp *rtcp_;
|
||||
|
||||
kvz_rtp::socket socket_;
|
||||
kvz_rtp::rtcp *rtcp_;
|
||||
private:
|
||||
bool reader_;
|
||||
|
||||
private:
|
||||
bool reader_;
|
||||
/* RTP */
|
||||
uint16_t rtp_sequence_;
|
||||
uint8_t rtp_payload_;
|
||||
uint32_t rtp_ssrc_;
|
||||
uint32_t rtp_timestamp_;
|
||||
uint64_t wc_start_;
|
||||
kvz_rtp::clock::hrc::hrc_t wc_start_2;
|
||||
uint32_t clock_rate_;
|
||||
|
||||
/* RTP */
|
||||
uint16_t rtp_sequence_;
|
||||
uint8_t rtp_payload_;
|
||||
uint32_t rtp_ssrc_;
|
||||
uint32_t rtp_timestamp_;
|
||||
uint64_t wc_start_;
|
||||
kvz_rtp::clock::hrc::hrc_t wc_start_2;
|
||||
uint32_t clock_rate_;
|
||||
kvz_rtp::frame_queue *fqueue_;
|
||||
|
||||
kvz_rtp::frame_queue *fqueue_;
|
||||
|
||||
kvz_rtp::dispatcher *dispatcher_;
|
||||
kvz_rtp::dispatcher *dispatcher_;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ kvz_rtp::dispatcher::dispatcher(kvz_rtp::socket *socket):
|
|||
kvz_rtp::dispatcher::~dispatcher()
|
||||
{
|
||||
delete runner_;
|
||||
runner_ = nullptr;
|
||||
}
|
||||
|
||||
rtp_error_t kvz_rtp::dispatcher::start()
|
||||
|
|
@ -30,11 +31,6 @@ rtp_error_t kvz_rtp::dispatcher::stop()
|
|||
return RTP_OK;
|
||||
}
|
||||
|
||||
bool kvz_rtp::dispatcher::active()
|
||||
{
|
||||
return active_;
|
||||
}
|
||||
|
||||
std::condition_variable& kvz_rtp::dispatcher::get_cvar()
|
||||
{
|
||||
return cv_;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "queue.hh"
|
||||
#include "socket.hh"
|
||||
#include "runner.hh"
|
||||
#include "util.hh"
|
||||
|
||||
namespace kvz_rtp {
|
||||
|
|
@ -30,15 +31,11 @@ namespace kvz_rtp {
|
|||
* experiences to very small (<50 us even for large frames [>170 kB]) */
|
||||
typedef struct transaction transaction_t;
|
||||
|
||||
class dispatcher {
|
||||
class dispatcher : public runner {
|
||||
public:
|
||||
dispatcher(kvz_rtp::socket *socket);
|
||||
~dispatcher();
|
||||
|
||||
rtp_error_t start();
|
||||
rtp_error_t stop();
|
||||
bool active();
|
||||
|
||||
/* Add new transaction to dispatcher's task queue
|
||||
* The task queue is emptied in FIFO style */
|
||||
rtp_error_t trigger_send(kvz_rtp::transaction_t *transaction);
|
||||
|
|
@ -62,9 +59,6 @@ namespace kvz_rtp {
|
|||
std::mutex q_mtx_;
|
||||
std::queue<kvz_rtp::transaction_t *> tasks_;
|
||||
|
||||
bool active_;
|
||||
std::thread *runner_;
|
||||
|
||||
kvz_rtp::socket *socket_;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
kvz_rtp::reader::reader(rtp_format_t fmt, std::string src_addr, int src_port):
|
||||
connection(fmt, true),
|
||||
active_(false),
|
||||
src_addr_(src_addr),
|
||||
src_port_(src_port),
|
||||
recv_hook_arg_(nullptr),
|
||||
|
|
@ -106,11 +105,6 @@ kvz_rtp::frame::rtp_frame *kvz_rtp::reader::pull_frame()
|
|||
return nextFrame;
|
||||
}
|
||||
|
||||
bool kvz_rtp::reader::active()
|
||||
{
|
||||
return active_;
|
||||
}
|
||||
|
||||
uint8_t *kvz_rtp::reader::get_recv_buffer() const
|
||||
{
|
||||
return recv_buffer_;
|
||||
|
|
|
|||
|
|
@ -16,11 +16,13 @@ namespace kvz_rtp {
|
|||
/* NOTE: this operation is blocking */
|
||||
kvz_rtp::frame::rtp_frame *pull_frame();
|
||||
|
||||
// open socket and start runner_
|
||||
/* Open socket, start frame receiver and RTCP
|
||||
*
|
||||
* Return RTP_OK on success
|
||||
* Return RTP_MEMORY_ERROR if memory deallocation failed
|
||||
* Return RTP_GENERIC_ERROR for any other error */
|
||||
rtp_error_t start();
|
||||
|
||||
bool active();
|
||||
|
||||
bool recv_hook_installed();
|
||||
void recv_hook(kvz_rtp::frame::rtp_frame *frame);
|
||||
void install_recv_hook(void *arg, void (*hook)(void *arg, kvz_rtp::frame::rtp_frame *));
|
||||
|
|
@ -44,15 +46,11 @@ namespace kvz_rtp {
|
|||
void return_frame(kvz_rtp::frame::rtp_frame *frame);
|
||||
|
||||
private:
|
||||
// TODO implement ring buffer
|
||||
bool active_;
|
||||
|
||||
// connection-related stuff
|
||||
std::string src_addr_;
|
||||
int src_port_;
|
||||
|
||||
// receiver thread related stuff
|
||||
std::thread *runner_;
|
||||
/* receiver thread related stuff */
|
||||
uint8_t *recv_buffer_; /* buffer for incoming packet (MAX_PACKET) */
|
||||
uint32_t recv_buffer_len_; /* buffer length */
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ kvz_rtp::rtcp::rtcp(uint32_t ssrc, bool receiver):
|
|||
tp_(0), tc_(0), tn_(0), pmembers_(0),
|
||||
members_(0), senders_(0), rtcp_bandwidth_(0),
|
||||
we_sent_(0), avg_rtcp_pkt_pize_(0), rtcp_pkt_count_(0),
|
||||
initial_(true), active_(false), num_receivers_(0)
|
||||
initial_(true), num_receivers_(0)
|
||||
{
|
||||
ssrc_ = ssrc;
|
||||
|
||||
|
|
@ -136,7 +136,7 @@ rtp_error_t kvz_rtp::rtcp::start()
|
|||
return RTP_OK;
|
||||
}
|
||||
|
||||
rtp_error_t kvz_rtp::rtcp::terminate()
|
||||
rtp_error_t kvz_rtp::rtcp::stop()
|
||||
{
|
||||
if (runner_ == nullptr)
|
||||
goto free_mem;
|
||||
|
|
@ -170,11 +170,6 @@ free_mem:
|
|||
return RTP_OK;
|
||||
}
|
||||
|
||||
bool kvz_rtp::rtcp::active() const
|
||||
{
|
||||
return active_;
|
||||
}
|
||||
|
||||
bool kvz_rtp::rtcp::receiver() const
|
||||
{
|
||||
return receiver_;
|
||||
|
|
|
|||
457
src/rtcp.hh
457
src/rtcp.hh
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include "clock.hh"
|
||||
#include "frame.hh"
|
||||
#include "runner.hh"
|
||||
#include "socket.hh"
|
||||
#include "util.hh"
|
||||
|
||||
|
|
@ -21,290 +22,280 @@ namespace kvz_rtp {
|
|||
const int MAX_MISORDER = 100;
|
||||
const int MIN_TIMEOUT = 5000;
|
||||
|
||||
class rtcp {
|
||||
public:
|
||||
rtcp(uint32_t ssrc, bool receiver);
|
||||
~rtcp();
|
||||
class rtcp : public runner {
|
||||
public:
|
||||
rtcp(uint32_t ssrc, bool receiver);
|
||||
~rtcp();
|
||||
|
||||
/* start the RTCP runner thread
|
||||
*
|
||||
* return RTP_OK on success and RTP_MEMORY_ERROR if the allocation fails */
|
||||
rtp_error_t start();
|
||||
/* start the RTCP runner thread
|
||||
*
|
||||
* return RTP_OK on success and RTP_MEMORY_ERROR if the allocation fails */
|
||||
rtp_error_t start();
|
||||
|
||||
/* End the RTCP session and send RTCP BYE to all participants
|
||||
*
|
||||
* return RTP_OK on success */
|
||||
rtp_error_t terminate();
|
||||
/* End the RTCP session and send RTCP BYE to all participants
|
||||
*
|
||||
* return RTP_OK on success */
|
||||
rtp_error_t stop();
|
||||
|
||||
/* return true if the connection is still considered active
|
||||
* and RTCP transmissions should continue */
|
||||
bool active() const;
|
||||
|
||||
/* return true if this RTCP instance belongs to an RTP receiver
|
||||
* and a receiver report should be generated, otherwise sender report is generated */
|
||||
bool receiver() const;
|
||||
/* return true if this RTCP instance belongs to an RTP receiver
|
||||
* and a receiver report should be generated, otherwise sender report is generated */
|
||||
bool receiver() const;
|
||||
|
||||
/* Generate either RTCP Sender or Receiver report and sent it to all participants
|
||||
* Return RTP_OK on success and RTP_ERROR on error */
|
||||
rtp_error_t generate_report();
|
||||
/* Generate either RTCP Sender or Receiver report and sent it to all participants
|
||||
* Return RTP_OK on success and RTP_ERROR on error */
|
||||
rtp_error_t generate_report();
|
||||
|
||||
/* Handle different kinds of incoming packets
|
||||
*
|
||||
* These routines will convert the fields of "frame" from network to host byte order
|
||||
*
|
||||
* Currently nothing's done with valid packets, at some point an API for
|
||||
* querying these reports is implemented
|
||||
*
|
||||
* Return RTP_OK on success and RTP_ERROR on error */
|
||||
rtp_error_t handle_sender_report_packet(kvz_rtp::frame::rtcp_sender_frame *frame, size_t size);
|
||||
rtp_error_t handle_receiver_report_packet(kvz_rtp::frame::rtcp_receiver_frame *frame, size_t size);
|
||||
rtp_error_t handle_sdes_packet(kvz_rtp::frame::rtcp_sdes_frame *frame, size_t size);
|
||||
rtp_error_t handle_bye_packet(kvz_rtp::frame::rtcp_bye_frame *frame, size_t size);
|
||||
rtp_error_t handle_app_packet(kvz_rtp::frame::rtcp_app_frame *frame, size_t size);
|
||||
/* Handle different kinds of incoming packets
|
||||
*
|
||||
* These routines will convert the fields of "frame" from network to host byte order
|
||||
*
|
||||
* Currently nothing's done with valid packets, at some point an API for
|
||||
* querying these reports is implemented
|
||||
*
|
||||
* Return RTP_OK on success and RTP_ERROR on error */
|
||||
rtp_error_t handle_sender_report_packet(kvz_rtp::frame::rtcp_sender_frame *frame, size_t size);
|
||||
rtp_error_t handle_receiver_report_packet(kvz_rtp::frame::rtcp_receiver_frame *frame, size_t size);
|
||||
rtp_error_t handle_sdes_packet(kvz_rtp::frame::rtcp_sdes_frame *frame, size_t size);
|
||||
rtp_error_t handle_bye_packet(kvz_rtp::frame::rtcp_bye_frame *frame, size_t size);
|
||||
rtp_error_t handle_app_packet(kvz_rtp::frame::rtcp_app_frame *frame, size_t size);
|
||||
|
||||
/* Handle incoming RTCP packet (first make sure it's a valid RTCP packet)
|
||||
* This function will call one of the above functions internally
|
||||
*
|
||||
* Return RTP_OK on success and RTP_ERROR on error */
|
||||
rtp_error_t handle_incoming_packet(uint8_t *buffer, size_t size);
|
||||
/* Handle incoming RTCP packet (first make sure it's a valid RTCP packet)
|
||||
* This function will call one of the above functions internally
|
||||
*
|
||||
* Return RTP_OK on success and RTP_ERROR on error */
|
||||
rtp_error_t handle_incoming_packet(uint8_t *buffer, size_t size);
|
||||
|
||||
/* Send "frame" to all participants
|
||||
*
|
||||
* These routines will convert all necessary fields to network byte order
|
||||
*
|
||||
* Return RTP_OK on success
|
||||
* Return RTP_INVALID_VALUE if "frame" is in some way invalid
|
||||
* Return RTP_SEND_ERROR if sending "frame" did not succeed (see socket.hh for details) */
|
||||
rtp_error_t send_sender_report_packet(kvz_rtp::frame::rtcp_sender_frame *frame);
|
||||
rtp_error_t send_receiver_report_packet(kvz_rtp::frame::rtcp_receiver_frame *frame);
|
||||
rtp_error_t send_sdes_packet(kvz_rtp::frame::rtcp_sdes_frame *frame);
|
||||
rtp_error_t send_bye_packet(kvz_rtp::frame::rtcp_bye_frame *frame);
|
||||
rtp_error_t send_app_packet(kvz_rtp::frame::rtcp_app_frame *frame);
|
||||
/* Send "frame" to all participants
|
||||
*
|
||||
* These routines will convert all necessary fields to network byte order
|
||||
*
|
||||
* Return RTP_OK on success
|
||||
* Return RTP_INVALID_VALUE if "frame" is in some way invalid
|
||||
* Return RTP_SEND_ERROR if sending "frame" did not succeed (see socket.hh for details) */
|
||||
rtp_error_t send_sender_report_packet(kvz_rtp::frame::rtcp_sender_frame *frame);
|
||||
rtp_error_t send_receiver_report_packet(kvz_rtp::frame::rtcp_receiver_frame *frame);
|
||||
rtp_error_t send_sdes_packet(kvz_rtp::frame::rtcp_sdes_frame *frame);
|
||||
rtp_error_t send_bye_packet(kvz_rtp::frame::rtcp_bye_frame *frame);
|
||||
rtp_error_t send_app_packet(kvz_rtp::frame::rtcp_app_frame *frame);
|
||||
|
||||
/* Return the latest RTCP packet received from participant of "ssrc"
|
||||
* Return nullptr if we haven't received this kind of packet or if "ssrc" doesn't exist
|
||||
*
|
||||
* NOTE: Caller is responsible for deallocating the memory */
|
||||
kvz_rtp::frame::rtcp_sender_frame *get_sender_packet(uint32_t ssrc);
|
||||
kvz_rtp::frame::rtcp_receiver_frame *get_receiver_packet(uint32_t ssrc);
|
||||
kvz_rtp::frame::rtcp_sdes_frame *get_sdes_packet(uint32_t ssrc);
|
||||
kvz_rtp::frame::rtcp_app_frame *get_app_packet(uint32_t ssrc);
|
||||
/* Return the latest RTCP packet received from participant of "ssrc"
|
||||
* Return nullptr if we haven't received this kind of packet or if "ssrc" doesn't exist
|
||||
*
|
||||
* NOTE: Caller is responsible for deallocating the memory */
|
||||
kvz_rtp::frame::rtcp_sender_frame *get_sender_packet(uint32_t ssrc);
|
||||
kvz_rtp::frame::rtcp_receiver_frame *get_receiver_packet(uint32_t ssrc);
|
||||
kvz_rtp::frame::rtcp_sdes_frame *get_sdes_packet(uint32_t ssrc);
|
||||
kvz_rtp::frame::rtcp_app_frame *get_app_packet(uint32_t ssrc);
|
||||
|
||||
/* create RTCP BYE packet using our own SSRC and send it to all participants */
|
||||
rtp_error_t terminate_self();
|
||||
/* create RTCP BYE packet using our own SSRC and send it to all participants */
|
||||
rtp_error_t terminate_self();
|
||||
|
||||
/* TODO: */
|
||||
std::vector<kvz_rtp::socket>& get_sockets();
|
||||
/* TODO: */
|
||||
std::vector<kvz_rtp::socket>& get_sockets();
|
||||
|
||||
/* Somebody joined the multicast group the owner of this RTCP instance is part of
|
||||
* Add it to RTCP participant list so we can start listening for reports
|
||||
*
|
||||
* "clock_rate" tells how much the RTP timestamp advances, this information is needed
|
||||
* to calculate the interarrival jitter correctly. It has nothing do with our clock rate,
|
||||
* (or whether we're even sending anything)
|
||||
*
|
||||
* Return RTP_OK on success and RTP_ERROR on error */
|
||||
rtp_error_t add_participant(std::string dst_addr, int dst_port, int src_port, uint32_t clock_rate);
|
||||
/* Somebody joined the multicast group the owner of this RTCP instance is part of
|
||||
* Add it to RTCP participant list so we can start listening for reports
|
||||
*
|
||||
* "clock_rate" tells how much the RTP timestamp advances, this information is needed
|
||||
* to calculate the interarrival jitter correctly. It has nothing do with our clock rate,
|
||||
* (or whether we're even sending anything)
|
||||
*
|
||||
* Return RTP_OK on success and RTP_ERROR on error */
|
||||
rtp_error_t add_participant(std::string dst_addr, int dst_port, int src_port, uint32_t clock_rate);
|
||||
|
||||
/* Functions for updating various RTP sender statistics */
|
||||
void sender_inc_seq_cycle_count();
|
||||
void sender_inc_sent_pkts(size_t n);
|
||||
void sender_inc_sent_bytes(size_t n);
|
||||
void sender_update_stats(kvz_rtp::frame::rtp_frame *frame);
|
||||
/* Functions for updating various RTP sender statistics */
|
||||
void sender_inc_seq_cycle_count();
|
||||
void sender_inc_sent_pkts(size_t n);
|
||||
void sender_inc_sent_bytes(size_t n);
|
||||
void sender_update_stats(kvz_rtp::frame::rtp_frame *frame);
|
||||
|
||||
void receiver_inc_sent_bytes(uint32_t sender_ssrc, size_t n);
|
||||
void receiver_inc_overhead_bytes(uint32_t sender_ssrc, size_t n);
|
||||
void receiver_inc_total_bytes(uint32_t sender_ssrc, size_t n);
|
||||
void receiver_inc_sent_pkts(uint32_t sender_ssrc, size_t n);
|
||||
void receiver_inc_sent_bytes(uint32_t sender_ssrc, size_t n);
|
||||
void receiver_inc_overhead_bytes(uint32_t sender_ssrc, size_t n);
|
||||
void receiver_inc_total_bytes(uint32_t sender_ssrc, size_t n);
|
||||
void receiver_inc_sent_pkts(uint32_t sender_ssrc, size_t n);
|
||||
|
||||
/* Update the RTCP statistics regarding this packet
|
||||
*
|
||||
* Return RTP_OK if packet is valid
|
||||
* Return RTP_INVALID_VALUE if SSRCs of remotes have collided or the packet is invalid in some way
|
||||
* return RTP_SSRC_COLLISION if our own SSRC has collided and we need to reinitialize it */
|
||||
rtp_error_t receiver_update_stats(kvz_rtp::frame::rtp_frame *frame);
|
||||
/* Update the RTCP statistics regarding this packet
|
||||
*
|
||||
* Return RTP_OK if packet is valid
|
||||
* Return RTP_INVALID_VALUE if SSRCs of remotes have collided or the packet is invalid in some way
|
||||
* return RTP_SSRC_COLLISION if our own SSRC has collided and we need to reinitialize it */
|
||||
rtp_error_t receiver_update_stats(kvz_rtp::frame::rtp_frame *frame);
|
||||
|
||||
/* If we've detected that our SSRC has collided with someone else's SSRC, we need to
|
||||
* generate new random SSRC and reinitialize our own RTCP state.
|
||||
* RTCP object still has the participants of "last session", we can use their SSRCs
|
||||
* to detected new collision
|
||||
*
|
||||
* Return RTP_OK if reinitialization succeeded
|
||||
* Return RTP_SSRC_COLLISION if our new SSRC has collided and we need to generate new SSRC */
|
||||
rtp_error_t reset_rtcp_state(uint32_t ssrc);
|
||||
/* If we've detected that our SSRC has collided with someone else's SSRC, we need to
|
||||
* generate new random SSRC and reinitialize our own RTCP state.
|
||||
* RTCP object still has the participants of "last session", we can use their SSRCs
|
||||
* to detected new collision
|
||||
*
|
||||
* Return RTP_OK if reinitialization succeeded
|
||||
* Return RTP_SSRC_COLLISION if our new SSRC has collided and we need to generate new SSRC */
|
||||
rtp_error_t reset_rtcp_state(uint32_t ssrc);
|
||||
|
||||
/* Set wallclock reading for t = 0 and random RTP timestamp from where the counting is started
|
||||
* + clock rate for calculating the correct increment */
|
||||
void set_sender_ts_info(uint64_t clock_start, uint32_t clock_rate, uint32_t rtp_ts_start);
|
||||
/* Set wallclock reading for t = 0 and random RTP timestamp from where the counting is started
|
||||
* + clock rate for calculating the correct increment */
|
||||
void set_sender_ts_info(uint64_t clock_start, uint32_t clock_rate, uint32_t rtp_ts_start);
|
||||
|
||||
/* Return SSRCs of all participants */
|
||||
std::vector<uint32_t> get_participants();
|
||||
/* Return SSRCs of all participants */
|
||||
std::vector<uint32_t> get_participants();
|
||||
|
||||
/* TODO: */
|
||||
rtp_error_t install_sender_hook(void (*hook)(kvz_rtp::frame::rtcp_sender_frame *));
|
||||
rtp_error_t install_receiver_hook(void (*hook)(kvz_rtp::frame::rtcp_receiver_frame *));
|
||||
rtp_error_t install_sdes_hook(void (*hook)(kvz_rtp::frame::rtcp_sdes_frame *));
|
||||
rtp_error_t install_app_hook(void (*hook)(kvz_rtp::frame::rtcp_app_frame *));
|
||||
/* TODO: */
|
||||
rtp_error_t install_sender_hook(void (*hook)(kvz_rtp::frame::rtcp_sender_frame *));
|
||||
rtp_error_t install_receiver_hook(void (*hook)(kvz_rtp::frame::rtcp_receiver_frame *));
|
||||
rtp_error_t install_sdes_hook(void (*hook)(kvz_rtp::frame::rtcp_sdes_frame *));
|
||||
rtp_error_t install_app_hook(void (*hook)(kvz_rtp::frame::rtcp_app_frame *));
|
||||
|
||||
private:
|
||||
static void rtcp_runner(rtcp *rtcp);
|
||||
private:
|
||||
static void rtcp_runner(rtcp *rtcp);
|
||||
|
||||
/* when we start the RTCP instance, we don't know what the SSRC of the remote is
|
||||
* when an RTP packet is received, we must check if we've already received a packet
|
||||
* from this sender and if not, create new entry to receiver_stats_ map */
|
||||
bool is_participant(uint32_t ssrc);
|
||||
/* when we start the RTCP instance, we don't know what the SSRC of the remote is
|
||||
* when an RTP packet is received, we must check if we've already received a packet
|
||||
* from this sender and if not, create new entry to receiver_stats_ map */
|
||||
bool is_participant(uint32_t ssrc);
|
||||
|
||||
/* When we receive an RTP or RTCP packet, we need to check the source address and see if it's
|
||||
* the same address where we've received packets before.
|
||||
*
|
||||
* If the address is new, it means we have detected an SSRC collision and the paket should
|
||||
* be dropped We also need to check whether this SSRC matches with our own SSRC and if it does
|
||||
* we need to send RTCP BYE and rejoin to the session */
|
||||
bool collision_detected(uint32_t ssrc, sockaddr_in& src_addr);
|
||||
/* When we receive an RTP or RTCP packet, we need to check the source address and see if it's
|
||||
* the same address where we've received packets before.
|
||||
*
|
||||
* If the address is new, it means we have detected an SSRC collision and the paket should
|
||||
* be dropped We also need to check whether this SSRC matches with our own SSRC and if it does
|
||||
* we need to send RTCP BYE and rejoin to the session */
|
||||
bool collision_detected(uint32_t ssrc, sockaddr_in& src_addr);
|
||||
|
||||
/* Move participant from initial_peers_ to participants_ */
|
||||
void add_participant(uint32_t ssrc);
|
||||
/* Move participant from initial_peers_ to participants_ */
|
||||
void add_participant(uint32_t ssrc);
|
||||
|
||||
/* We've got a message from new source (the SSRC of the frame is not known to us)
|
||||
* Initialize statistics for the peer and move it to participants_ */
|
||||
void init_new_participant(kvz_rtp::frame::rtp_frame *frame);
|
||||
/* We've got a message from new source (the SSRC of the frame is not known to us)
|
||||
* Initialize statistics for the peer and move it to participants_ */
|
||||
void init_new_participant(kvz_rtp::frame::rtp_frame *frame);
|
||||
|
||||
/* Initialize the RTP Sequence related stuff of peer
|
||||
* This function assumes that the peer already exists in the participants_ map */
|
||||
void init_participant_seq(uint32_t ssrc, uint16_t base_seq);
|
||||
/* Initialize the RTP Sequence related stuff of peer
|
||||
* This function assumes that the peer already exists in the participants_ map */
|
||||
void init_participant_seq(uint32_t ssrc, uint16_t base_seq);
|
||||
|
||||
/* Update the SSRC's sequence related data in participants_ map
|
||||
*
|
||||
* Return RTP_OK if the received packet was OK
|
||||
* Return RTP_GENERIC_ERROR if it wasn't and
|
||||
* packet-related statistics should not be updated */
|
||||
rtp_error_t update_participant_seq(uint32_t ssrc, uint16_t seq);
|
||||
/* Update the SSRC's sequence related data in participants_ map
|
||||
*
|
||||
* Return RTP_OK if the received packet was OK
|
||||
* Return RTP_GENERIC_ERROR if it wasn't and
|
||||
* packet-related statistics should not be updated */
|
||||
rtp_error_t update_participant_seq(uint32_t ssrc, uint16_t seq);
|
||||
|
||||
/* Update the RTCP bandwidth variables
|
||||
*
|
||||
* "pkt_size" tells how much rtcp_byte_count_
|
||||
* should be increased before calculating the new average */
|
||||
void update_rtcp_bandwidth(size_t pkt_size);
|
||||
/* Update the RTCP bandwidth variables
|
||||
*
|
||||
* "pkt_size" tells how much rtcp_byte_count_
|
||||
* should be increased before calculating the new average */
|
||||
void update_rtcp_bandwidth(size_t pkt_size);
|
||||
|
||||
/* Functions for generating different kinds of reports.
|
||||
* These functions will both generate the report and send it
|
||||
*
|
||||
* Return RTP_OK on success and RTP_ERROR on error */
|
||||
rtp_error_t generate_sender_report();
|
||||
rtp_error_t generate_receiver_report();
|
||||
/* Functions for generating different kinds of reports.
|
||||
* These functions will both generate the report and send it
|
||||
*
|
||||
* Return RTP_OK on success and RTP_ERROR on error */
|
||||
rtp_error_t generate_sender_report();
|
||||
rtp_error_t generate_receiver_report();
|
||||
|
||||
std::thread *runner_;
|
||||
bool receiver_;
|
||||
bool receiver_;
|
||||
|
||||
/* TODO: time_t?? */
|
||||
size_t tp_; /* the last time an RTCP packet was transmitted */
|
||||
size_t tc_; /* the current time */
|
||||
size_t tn_; /* the next scheduled transmission time of an RTCP packet */
|
||||
size_t pmembers_; /* the estimated number of session members at the time tn was last recomputed */
|
||||
size_t members_; /* the most current estimate for the number of session members */
|
||||
size_t senders_; /* the most current estimate for the number of senders in the session */
|
||||
/* TODO: time_t?? */
|
||||
size_t tp_; /* the last time an RTCP packet was transmitted */
|
||||
size_t tc_; /* the current time */
|
||||
size_t tn_; /* the next scheduled transmission time of an RTCP packet */
|
||||
size_t pmembers_; /* the estimated number of session members at the time tn was last recomputed */
|
||||
size_t members_; /* the most current estimate for the number of session members */
|
||||
size_t senders_; /* the most current estimate for the number of senders in the session */
|
||||
|
||||
/* The target RTCP bandwidth, i.e., the total bandwidth
|
||||
* that will be used for RTCP packets by all members of this session,
|
||||
* in octets per second. This will be a specified fraction of the
|
||||
* "session bandwidth" parameter supplied to the application at startup. */
|
||||
size_t rtcp_bandwidth_;
|
||||
/* The target RTCP bandwidth, i.e., the total bandwidth
|
||||
* that will be used for RTCP packets by all members of this session,
|
||||
* in octets per second. This will be a specified fraction of the
|
||||
* "session bandwidth" parameter supplied to the application at startup. */
|
||||
size_t rtcp_bandwidth_;
|
||||
|
||||
/* Flag that is true if the application has sent data since
|
||||
* the 2nd previous RTCP report was transmitted. */
|
||||
bool we_sent_;
|
||||
/* Flag that is true if the application has sent data since
|
||||
* the 2nd previous RTCP report was transmitted. */
|
||||
bool we_sent_;
|
||||
|
||||
/* The average compound RTCP packet size, in octets,
|
||||
* over all RTCP packets sent and received by this participant. The
|
||||
* size includes lower-layer transport and network protocol headers
|
||||
* (e.g., UDP and IP) as explained in Section 6.2 */
|
||||
size_t avg_rtcp_pkt_pize_;
|
||||
/* The average compound RTCP packet size, in octets,
|
||||
* over all RTCP packets sent and received by this participant. The
|
||||
* size includes lower-layer transport and network protocol headers
|
||||
* (e.g., UDP and IP) as explained in Section 6.2 */
|
||||
size_t avg_rtcp_pkt_pize_;
|
||||
|
||||
/* Number of RTCP packets and bytes sent and received by this participant */
|
||||
size_t rtcp_pkt_count_;
|
||||
size_t rtcp_byte_count_;
|
||||
/* Number of RTCP packets and bytes sent and received by this participant */
|
||||
size_t rtcp_pkt_count_;
|
||||
size_t rtcp_byte_count_;
|
||||
|
||||
/* Flag that is true if the application has not yet sent an RTCP packet. */
|
||||
bool initial_;
|
||||
/* Flag that is true if the application has not yet sent an RTCP packet. */
|
||||
bool initial_;
|
||||
|
||||
/* Flag that is true if the connection is still considered open.
|
||||
* When clients decided to leave, he calls rtcp->terminate()
|
||||
* which stops the rtcp runner and RTCP BYE message to all participants */
|
||||
bool active_;
|
||||
/* Copy of our own current SSRC */
|
||||
uint32_t ssrc_;
|
||||
|
||||
/* Copy of our own current SSRC */
|
||||
uint32_t ssrc_;
|
||||
/* NTP timestamp associated with initial RTP timestamp (aka t = 0) */
|
||||
uint64_t clock_start_;
|
||||
|
||||
/* NTP timestamp associated with initial RTP timestamp (aka t = 0) */
|
||||
uint64_t clock_start_;
|
||||
/* Clock rate of the media ie. how fast does the time increase */
|
||||
uint32_t clock_rate_;
|
||||
|
||||
/* Clock rate of the media ie. how fast does the time increase */
|
||||
uint32_t clock_rate_;
|
||||
/* The first value of RTP timestamp (aka t = 0) */
|
||||
uint32_t rtp_ts_start_;
|
||||
|
||||
/* The first value of RTP timestamp (aka t = 0) */
|
||||
uint32_t rtp_ts_start_;
|
||||
struct statistics {
|
||||
/* receiver stats */
|
||||
uint32_t received_pkts; /* Number of packets received */
|
||||
uint32_t dropped_pkts; /* Number of dropped RTP packets */
|
||||
uint32_t received_bytes; /* Number of bytes received excluding RTP Header */
|
||||
|
||||
struct statistics {
|
||||
/* receiver stats */
|
||||
uint32_t received_pkts; /* Number of packets received */
|
||||
uint32_t dropped_pkts; /* Number of dropped RTP packets */
|
||||
uint32_t received_bytes; /* Number of bytes received excluding RTP Header */
|
||||
/* sender stats */
|
||||
uint32_t sent_pkts; /* Number of sent RTP packets */
|
||||
uint32_t sent_bytes; /* Number of sent bytes excluding RTP Header */
|
||||
|
||||
/* sender stats */
|
||||
uint32_t sent_pkts; /* Number of sent RTP packets */
|
||||
uint32_t sent_bytes; /* Number of sent bytes excluding RTP Header */
|
||||
uint32_t jitter; /* TODO: */
|
||||
uint32_t transit; /* TODO: */
|
||||
|
||||
uint32_t jitter; /* TODO: */
|
||||
uint32_t transit; /* TODO: */
|
||||
/* Receiver clock related stuff */
|
||||
uint64_t initial_ntp; /* Wallclock reading when the first RTP packet was received */
|
||||
uint32_t initial_rtp; /* RTP timestamp of the first RTP packet received */
|
||||
uint32_t clock_rate; /* Rate of the clock (used for jitter calculations) */
|
||||
|
||||
/* Receiver clock related stuff */
|
||||
uint64_t initial_ntp; /* Wallclock reading when the first RTP packet was received */
|
||||
uint32_t initial_rtp; /* RTP timestamp of the first RTP packet received */
|
||||
uint32_t clock_rate; /* Rate of the clock (used for jitter calculations) */
|
||||
uint32_t lsr; /* Middle 32 bits of the 64-bit NTP timestamp of previous SR */
|
||||
kvz_rtp::clock::hrc::hrc_t sr_ts; /* When the last SR was received (used to calculate delay) */
|
||||
|
||||
uint32_t lsr; /* Middle 32 bits of the 64-bit NTP timestamp of previous SR */
|
||||
kvz_rtp::clock::hrc::hrc_t sr_ts; /* When the last SR was received (used to calculate delay) */
|
||||
uint16_t max_seq; /* Highest sequence number received */
|
||||
uint16_t base_seq; /* First sequence number received */
|
||||
uint16_t bad_seq; /* TODO: */
|
||||
uint16_t cycles; /* Number of sequence cycles */
|
||||
};
|
||||
|
||||
uint16_t max_seq; /* Highest sequence number received */
|
||||
uint16_t base_seq; /* First sequence number received */
|
||||
uint16_t bad_seq; /* TODO: */
|
||||
uint16_t cycles; /* Number of sequence cycles */
|
||||
};
|
||||
struct participant {
|
||||
kvz_rtp::socket *socket; /* socket associated with this participant */
|
||||
sockaddr_in address; /* address of the participant */
|
||||
struct statistics stats; /* RTCP session statistics of the participant */
|
||||
|
||||
struct participant {
|
||||
kvz_rtp::socket *socket; /* socket associated with this participant */
|
||||
sockaddr_in address; /* address of the participant */
|
||||
struct statistics stats; /* RTCP session statistics of the participant */
|
||||
int probation; /* TODO: */
|
||||
bool sender; /* Sender will create report block for other sender only */
|
||||
|
||||
int probation; /* TODO: */
|
||||
bool sender; /* Sender will create report block for other sender only */
|
||||
/* Save the latest RTCP packets received from this participant
|
||||
* Users can query these packets using the SSRC of participant */
|
||||
kvz_rtp::frame::rtcp_sender_frame *s_frame;
|
||||
kvz_rtp::frame::rtcp_receiver_frame *r_frame;
|
||||
kvz_rtp::frame::rtcp_sdes_frame *sdes_frame;
|
||||
kvz_rtp::frame::rtcp_app_frame *app_frame;
|
||||
};
|
||||
|
||||
/* Save the latest RTCP packets received from this participant
|
||||
* Users can query these packets using the SSRC of participant */
|
||||
kvz_rtp::frame::rtcp_sender_frame *s_frame;
|
||||
kvz_rtp::frame::rtcp_receiver_frame *r_frame;
|
||||
kvz_rtp::frame::rtcp_sdes_frame *sdes_frame;
|
||||
kvz_rtp::frame::rtcp_app_frame *app_frame;
|
||||
};
|
||||
std::map<uint32_t, struct participant *> participants_;
|
||||
size_t num_receivers_;
|
||||
|
||||
std::map<uint32_t, struct participant *> participants_;
|
||||
size_t num_receivers_;
|
||||
/* statistics for RTCP Sender and Receiver Reports */
|
||||
struct statistics sender_stats;
|
||||
|
||||
/* statistics for RTCP Sender and Receiver Reports */
|
||||
struct statistics sender_stats;
|
||||
/* TODO: */
|
||||
std::vector<struct participant *> initial_participants_;
|
||||
|
||||
/* TODO: */
|
||||
std::vector<struct participant *> initial_participants_;
|
||||
/* Vector of sockets the RTCP runner is listening to
|
||||
*
|
||||
* The socket are also stored here (in addition to participants_ map) so they're easier
|
||||
* to pass to poll when RTCP runner is listening to incoming packets */
|
||||
std::vector<kvz_rtp::socket> sockets_;
|
||||
|
||||
/* Vector of sockets the RTCP runner is listening to
|
||||
*
|
||||
* The socket are also stored here (in addition to participants_ map) so they're easier
|
||||
* to pass to poll when RTCP runner is listening to incoming packets */
|
||||
std::vector<kvz_rtp::socket> sockets_;
|
||||
|
||||
void (*sender_hook_)(kvz_rtp::frame::rtcp_sender_frame *);
|
||||
void (*receiver_hook_)(kvz_rtp::frame::rtcp_receiver_frame *);
|
||||
void (*sdes_hook_)(kvz_rtp::frame::rtcp_sdes_frame *);
|
||||
void (*app_hook_)(kvz_rtp::frame::rtcp_app_frame *);
|
||||
void (*sender_hook_)(kvz_rtp::frame::rtcp_sender_frame *);
|
||||
void (*receiver_hook_)(kvz_rtp::frame::rtcp_receiver_frame *);
|
||||
void (*sdes_hook_)(kvz_rtp::frame::rtcp_sdes_frame *);
|
||||
void (*app_hook_)(kvz_rtp::frame::rtcp_app_frame *);
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
#include "runner.hh"
|
||||
|
||||
kvz_rtp::runner::runner():
|
||||
active_(false), runner_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
kvz_rtp::runner::~runner()
|
||||
{
|
||||
active_ = false;
|
||||
|
||||
if (runner_)
|
||||
delete runner_;
|
||||
}
|
||||
|
||||
rtp_error_t kvz_rtp::runner::start()
|
||||
{
|
||||
active_ = true;
|
||||
}
|
||||
|
||||
rtp_error_t kvz_rtp::runner::stop()
|
||||
{
|
||||
active_ = false;
|
||||
active_ = false;
|
||||
}
|
||||
|
||||
bool kvz_rtp::runner::active()
|
||||
{
|
||||
return active_;
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
#pragma once
|
||||
|
||||
#include <thread>
|
||||
|
||||
#include "util.hh"
|
||||
|
||||
namespace kvz_rtp {
|
||||
class runner {
|
||||
public:
|
||||
runner();
|
||||
virtual ~runner();
|
||||
|
||||
virtual rtp_error_t start();
|
||||
virtual rtp_error_t stop();
|
||||
|
||||
virtual bool active();
|
||||
|
||||
protected:
|
||||
bool active_;
|
||||
std::thread *runner_;
|
||||
};
|
||||
};
|
||||
Loading…
Reference in New Issue