diff --git a/include/formats/hevc.hh b/include/formats/hevc.hh index 758641c..6c0b588 100644 --- a/include/formats/hevc.hh +++ b/include/formats/hevc.hh @@ -33,7 +33,7 @@ namespace uvg_rtp { * Return RTP_PKT_NOT_HANDLED if the packet is not handled by this handler * Return RTP_PKT_MODIFIED if the packet was modified but should be forwarded to other handlers * Return RTP_GENERIC_ERROR if the packet was corrupted in some way */ - static rtp_error_t packet_handler(int flags, frame::rtp_frame **frame); + static rtp_error_t packet_handler(void *arg, int flags, frame::rtp_frame **frame); protected: rtp_error_t __push_frame(uint8_t *data, size_t data_len, int flags); diff --git a/include/formats/media.hh b/include/formats/media.hh index a08af5a..891bec9 100644 --- a/include/formats/media.hh +++ b/include/formats/media.hh @@ -33,7 +33,7 @@ namespace uvg_rtp { * Return RTP_PKT_NOT_HANDLED if the packet is not handled by this handler * Return RTP_PKT_MODIFIED if the packet was modified but should be forwarded to other handlers * Return RTP_GENERIC_ERROR if the packet was corrupted in some way */ - static rtp_error_t packet_handler(int flags, frame::rtp_frame **frame); + static rtp_error_t packet_handler(void *arg, int flags, frame::rtp_frame **frame); protected: virtual rtp_error_t __push_frame(uint8_t *data, size_t data_len, int flags); diff --git a/include/pkt_dispatch.hh b/include/pkt_dispatch.hh index 6a835f4..a1e071a 100644 --- a/include/pkt_dispatch.hh +++ b/include/pkt_dispatch.hh @@ -11,11 +11,16 @@ namespace uvg_rtp { typedef rtp_error_t (*packet_handler)(ssize_t, void *, int, uvg_rtp::frame::rtp_frame **); - typedef rtp_error_t (*packet_handler_aux)(int, uvg_rtp::frame::rtp_frame **); + typedef rtp_error_t (*packet_handler_aux)(void *, int, uvg_rtp::frame::rtp_frame **); + + struct auxiliary_handler { + void *arg; + packet_handler_aux handler; + }; struct packet_handlers { packet_handler primary; - std::vector auxiliary; + std::vector auxiliary; }; class pkt_dispatcher : public runner { @@ -44,9 +49,12 @@ namespace uvg_rtp { * "key" is used to specify for which primary handlers for "handler" * An auxiliary handler can be installed to multiple primary handlers * + * "arg" is an optional argument that is passed to the handler when it's called + * It can be null if the handler does not require additional data + * * Return RTP_OK on success * Return RTP_INVALID_VALUE if "handler" is nullptr or if "key" is not valid */ - rtp_error_t install_aux_handler(uint32_t key, packet_handler_aux handler); + rtp_error_t install_aux_handler(uint32_t key, void *arg, packet_handler_aux handler); /* Install receive hook for the RTP packet dispatcher * diff --git a/include/rtcp.hh b/include/rtcp.hh index 636ecbf..5179cd9 100644 --- a/include/rtcp.hh +++ b/include/rtcp.hh @@ -141,7 +141,7 @@ namespace uvg_rtp { rtp_error_t install_app_hook(void (*hook)(uvg_rtp::frame::rtcp_app_frame *)); /* Update RTCP-related session statistics */ - static rtp_error_t packet_handler(int flags, frame::rtp_frame **out); + static rtp_error_t packet_handler(void *arg, int flags, frame::rtp_frame **out); private: static void rtcp_runner(rtcp *rtcp); diff --git a/src/formats/hevc_pkt_handler.cc b/src/formats/hevc_pkt_handler.cc index 8d26b8d..4123c53 100644 --- a/src/formats/hevc_pkt_handler.cc +++ b/src/formats/hevc_pkt_handler.cc @@ -102,8 +102,10 @@ static void __drop_frame(frame_info_t& finfo, uint32_t ts) finfo.erase(ts); } -rtp_error_t uvg_rtp::formats::hevc::packet_handler(int flags, uvg_rtp::frame::rtp_frame **out) +rtp_error_t uvg_rtp::formats::hevc::packet_handler(void *arg, int flags, uvg_rtp::frame::rtp_frame **out) { + (void)arg; + static frame_info_t finfo; static std::unordered_set dropped; diff --git a/src/formats/media.cc b/src/formats/media.cc index 253477a..c87009b 100644 --- a/src/formats/media.cc +++ b/src/formats/media.cc @@ -92,8 +92,10 @@ rtp_error_t uvg_rtp::formats::media::__push_frame(uint8_t *data, size_t data_len return socket_->sendto(buffers, 0); } -rtp_error_t uvg_rtp::formats::media::packet_handler(int flags, uvg_rtp::frame::rtp_frame **out) +rtp_error_t uvg_rtp::formats::media::packet_handler(void *arg, int flags, uvg_rtp::frame::rtp_frame **out) { + (void)arg; + struct frame_info { uint32_t s_seq; uint32_t e_seq; diff --git a/src/media_stream.cc b/src/media_stream.cc index c227d16..bf5ff76 100644 --- a/src/media_stream.cc +++ b/src/media_stream.cc @@ -117,13 +117,14 @@ rtp_error_t uvg_rtp::media_stream::init() } rtp_handler_key_ = pkt_dispatcher_->install_handler(rtp_->packet_handler); - pkt_dispatcher_->install_aux_handler(rtp_handler_key_, rtcp_->packet_handler); + pkt_dispatcher_->install_aux_handler(rtp_handler_key_, rtcp_, rtcp_->packet_handler); switch (fmt_) { case RTP_FORMAT_HEVC: media_ = new uvg_rtp::formats::hevc(&socket_, rtp_, ctx_config_.flags); pkt_dispatcher_->install_aux_handler( rtp_handler_key_, + nullptr, dynamic_cast(media_)->packet_handler ); break; @@ -131,7 +132,7 @@ rtp_error_t uvg_rtp::media_stream::init() case RTP_FORMAT_OPUS: case RTP_FORMAT_GENERIC: media_ = new uvg_rtp::formats::media(&socket_, rtp_, ctx_config_.flags); - pkt_dispatcher_->install_aux_handler(rtp_handler_key_, media_->packet_handler); + pkt_dispatcher_->install_aux_handler(rtp_handler_key_, nullptr, media_->packet_handler); break; default: diff --git a/src/pkt_dispatch.cc b/src/pkt_dispatch.cc index e2e1bce..4bce2cc 100644 --- a/src/pkt_dispatch.cc +++ b/src/pkt_dispatch.cc @@ -104,7 +104,11 @@ uint32_t uvg_rtp::pkt_dispatcher::install_handler(uvg_rtp::packet_handler handle return key; } -rtp_error_t uvg_rtp::pkt_dispatcher::install_aux_handler(uint32_t key, uvg_rtp::packet_handler_aux handler) +rtp_error_t uvg_rtp::pkt_dispatcher::install_aux_handler( + uint32_t key, + void *arg, + uvg_rtp::packet_handler_aux handler +) { if (!handler) return RTP_INVALID_VALUE; @@ -112,7 +116,7 @@ rtp_error_t uvg_rtp::pkt_dispatcher::install_aux_handler(uint32_t key, uvg_rtp:: if (packet_handlers_.find(key) == packet_handlers_.end()) return RTP_INVALID_VALUE; - packet_handlers_[key].auxiliary.push_back(handler); + packet_handlers_[key].auxiliary.push_back({ arg, handler }); return RTP_OK; } @@ -136,8 +140,8 @@ void uvg_rtp::pkt_dispatcher::call_aux_handlers(uint32_t key, int flags, uvg_rtp { rtp_error_t ret; - for (auto& handler : packet_handlers_[key].auxiliary) { - switch ((ret = (*handler)(flags, frame))) { + for (auto& aux : packet_handlers_[key].auxiliary) { + switch ((ret = (*aux.handler)(aux.arg, flags, frame))) { /* packet was handled successfully */ case RTP_OK: break; diff --git a/src/rtcp.cc b/src/rtcp.cc index 6c1a052..bddcfb0 100644 --- a/src/rtcp.cc +++ b/src/rtcp.cc @@ -605,7 +605,17 @@ void uvg_rtp::rtcp::rtcp_runner(uvg_rtp::rtcp *rtcp) } } -rtp_error_t uvg_rtp::rtcp::packet_handler(int flags, frame::rtp_frame **out) +/* RTCP packet handler is responsible for doing two things: + * + * - it checks whether the packet is coming from an existing user and if so, + * updates that user's session statistics. If the packet is coming from a user, + * the user is put on probation where they will stay until enough valid packets + * have been received. + * - it keeps track of participants' SSRCs and if a collision + * is detected, the RTP context is updated */ +rtp_error_t uvg_rtp::rtcp::packet_handler(void *arg, int flags, frame::rtp_frame **out) { + (void)arg, (void)flags, (void)out; + return RTP_PKT_NOT_HANDLED; }