6464#include "rtp_packet.h"
6565#include "rtp_packet_priv.h"
6666#include "rtpp_packetport.h"
67+ #include "librtpproxy/packetport.h"
6768#include "rtpp_packet_ext.h"
6869#include "rtpp_pipe.h"
6970#include "rtpp_session.h"
8081#define RTPP_PACKETPORT_IN_PORT0 2
8182#define RTPP_PPSIG_TERM 0
8283#define RTPP_PPSIG_NUDGE 1
84+ #define RTPP_PPSIG_FLUSH 2
8385
8486static const struct timespec rtpp_packetport_tick = {
8587 .tv_sec = 0 ,
@@ -93,6 +95,13 @@ struct rtpp_packetport_int_priv {
9395 unsigned int capacity ;
9496 _Atomic (unsigned int ) out_port ;
9597 _Atomic (unsigned int ) in_port ;
98+ struct {
99+ _Atomic (uint64_t ) out_run ;
100+ uint64_t out_run_lc ;
101+ } __attribute__((aligned (CACHELINE_SIZE ))) out_run_state ;
102+ struct {
103+ uint64_t last_flush_run ;
104+ } __attribute__((aligned (CACHELINE_SIZE ))) flush_state ;
96105 pthread_t worker_id ;
97106 struct rtpp_queue * pqueue ;
98107 struct rtpp_hash_table * streams_ht ;
@@ -136,6 +145,7 @@ static int rtpp_packetport_queue_wi(struct rtpp_packetport_int_priv *,
136145 struct rtpp_wi * );
137146static int rtpp_packetport_proc_wi_batch (struct rtpp_packetport_int_priv * ,
138147 struct rtpp_wi * * , int );
148+ static uint64_t rtpp_packetport_out_run (struct rtpp_packetport_int_priv * );
139149static void rtpp_packetport_drain_queue (struct SPMCQueue * );
140150static void rtpp_packetport_drain_out (struct rtpp_packetport_int_priv * );
141151static int rtpp_packetport_ismapped (const void * );
@@ -318,6 +328,8 @@ rtpp_packetport_ctor(unsigned int capacity)
318328 pvt -> id = RTPP_PACKETPORT_PRIV_ID ;
319329 atomic_init (& pvt -> out_port , (unsigned int )RTPP_PACKETPORT_OUT_PORT0 );
320330 atomic_init (& pvt -> in_port , (unsigned int )RTPP_PACKETPORT_IN_PORT0 );
331+ atomic_init (& pvt -> out_run_state .out_run , 0 );
332+ pvt -> flush_state .last_flush_run = UINT64_MAX ;
321333 PUBINST_FININIT (& pvt -> pub , pvt , rtpp_packetport_dtor_obj );
322334#if HAVE_PTHREAD_SETNAME_NP
323335 (void )pthread_setname_np (pvt -> worker_id , "rtpp_packetport" );
@@ -348,6 +360,31 @@ rtpp_packetport_try_push(struct rtpp_packetport *ext, struct rtp_packet_ext *pkt
348360 return (try_push (pvt -> ext .out , pktxp ) ? 0 : -1 );
349361}
350362
363+ int
364+ rtpp_packetport_flush (struct rtpp_packetport * ext )
365+ {
366+ struct rtpp_packetport_int_priv * pvt ;
367+ struct rtpp_wi * wi ;
368+ uint64_t seen_run ;
369+
370+ EXT2PVT (ext , pvt );
371+ seen_run = atomic_load_explicit (& pvt -> out_run_state .out_run ,
372+ memory_order_relaxed );
373+ if (seen_run == pvt -> flush_state .last_flush_run ) {
374+ return (0 );
375+ }
376+ wi = rtpp_wi_malloc_sgnl (RTPP_PPSIG_FLUSH , & seen_run , sizeof (seen_run ));
377+ if (wi == NULL ) {
378+ return (-1 );
379+ }
380+ if (rtpp_queue_put_item (wi , pvt -> pqueue ) != 0 ) {
381+ RTPP_OBJ_DECREF (wi );
382+ return (-1 );
383+ }
384+ pvt -> flush_state .last_flush_run = seen_run ;
385+ return (0 );
386+ }
387+
351388struct rtpp_packetport_int *
352389rtpp_packetport_get_int (struct rtpp_packetport * ext )
353390{
@@ -424,14 +461,16 @@ rtpp_packetport_run(void *argp)
424461 if (qlen == 0 )
425462 qlen = CALL_SMETHOD (pvt -> streams_ht , get_length ) > 0 ? 16 : 0 ;
426463 if (qlen > 0 ) {
427- rtpp_packetport_drain_out (pvt );
428464 if (ddp == NULL ) {
429465 ddp = & deadline ;
430466 dtime2mtimespec (getdtime (), ddp );
431467 }
432- rtpp_packetport_deadline_step (ddp );
433468 nwis = rtpp_queue_get_items_by (pvt -> pqueue , pvt -> wi_batch ,
434469 (int )pvt -> capacity , ddp , NULL );
470+ if (nwis == 0 ) {
471+ rtpp_packetport_drain_out (pvt );
472+ rtpp_packetport_deadline_step (ddp );
473+ }
435474 qlen -= 1 ;
436475 } else {
437476 ddp = NULL ;
@@ -579,16 +618,31 @@ rtpp_packetport_proc_wi_batch(struct rtpp_packetport_int_priv *pvt,
579618 struct rtpp_wi_pvt * wipp ;
580619 struct rtp_packet_ext * pktxp ;
581620 struct rtp_packet * pktp ;
582- int i , signum , term_seen ;
621+ uint64_t sig_run ;
622+ size_t dlen ;
623+ int flush_seen , i , signum , term_seen ;
583624
584625 term_seen = 0 ;
626+ flush_seen = 0 ;
585627 for (i = 0 ; i < nwis ; i ++ ) {
586628 if (wis [i ]-> wi_type == RTPP_WI_TYPE_SGNL ) {
587629 signum = rtpp_wi_sgnl_get_signum (wis [i ]);
588630 if (signum == RTPP_PPSIG_TERM ) {
589631 term_seen = 1 ;
590632 break ;
591633 }
634+ if (signum == RTPP_PPSIG_FLUSH ) {
635+ const uint64_t * srp ;
636+
637+ srp = rtpp_wi_sgnl_get_data (wis [i ], & dlen );
638+ if (dlen == sizeof (* srp )) {
639+ sig_run = * srp ;
640+ if (sig_run >= pvt -> out_run_state .out_run_lc ) {
641+ flush_seen = 1 ;
642+ }
643+ }
644+ continue ;
645+ }
592646 RTPP_DBG_ASSERT (signum == RTPP_PPSIG_NUDGE );
593647 continue ;
594648 }
@@ -606,9 +660,23 @@ rtpp_packetport_proc_wi_batch(struct rtpp_packetport_int_priv *pvt,
606660 RTPP_OBJ_DECREF (wis [i ]);
607661 if (term_seen != 0 )
608662 return (-1 );
663+ if (flush_seen != 0 ) {
664+ rtpp_packetport_drain_out (pvt );
665+ }
609666 return (0 );
610667}
611668
669+ static uint64_t
670+ rtpp_packetport_out_run (struct rtpp_packetport_int_priv * pvt )
671+ {
672+ uint64_t run ;
673+
674+ run = atomic_fetch_add_explicit (& pvt -> out_run_state .out_run , 1 ,
675+ memory_order_relaxed ) + 1 ;
676+ pvt -> out_run_state .out_run_lc = run ;
677+ return (run );
678+ }
679+
612680static void
613681rtpp_packetport_drain_queue (struct SPMCQueue * queue )
614682{
@@ -631,6 +699,7 @@ rtpp_packetport_drain_out(struct rtpp_packetport_int_priv *pvt)
631699 struct pkt_proc_ctx pktx ;
632700 size_t i , nitems ;
633701
702+ (void )rtpp_packetport_out_run (pvt );
634703 while ((nitems = try_pop_many (pvt -> ext .out , pvt -> out_batch ,
635704 (size_t )pvt -> capacity )) > 0 ) {
636705 for (i = 0 ; i < nitems ; i ++ ) {
0 commit comments