/***************************************************************************** * RetxQueue: store a packet in the retx queue *****************************************************************************/ static void RetxQueue( block_t *p_block, uint64_t i_current_date ) { p_block->i_date = i_current_date; p_block->p_next = NULL; rtp_set_marker( p_block->p_data ); /* Queue block */ if ( p_retx_last != NULL ) { p_retx_last->p_next = p_block; p_retx_last = p_block; } else p_retx_last = p_retx_first = p_block; /* Purge old blocks */ while ( p_retx_first != NULL && p_retx_first->i_date < i_current_date - i_retx_buffer ) { block_t *p_next = p_retx_first->p_next; free(p_retx_first); p_retx_first = p_next; } if ( p_retx_first == NULL ) p_retx_last = NULL; }
int main(int argc, char *argv[]) { #ifndef RTPESND char p_header[PIPE_HEADER_LEN]; #endif RTPSEND char r_header[RTP_HEADER_LEN]; char *buffer; struct iovec iov[3]; ssize_t length; u_int16_t seq; PIPE_CONTEXT p; int dummy_cnt; /* dummy(very old packet)cnt */ #ifdef RTPSEND int count=0; /* for Debug */ struct timeval blk_start_tv; int blk_wait4start=1; int blk_pktcnt = 0; u_int32_t waitperframe; #endif sigset_t sigset; ssize_t io_ret; /* sigfillset(&sigset); */ /* sigdelset(&sigset,SIGINT); */ /* sigdelset(&sigset,SIGTSTP); */ if (sigprocmask(SIG_BLOCK,&sigset,NULL)!=0){ e_printf("sigprocmask fail.\n"); exit(0); } signal(SIGINT,cb_sig); signal(SIGTSTP,cb_sig); signal(SIGPIPE,cb_sig); if (opt_etc(argc, argv) == -1) { return -1; } if (isatty(STDIN)) { e_printf("Standard input must be binded with pipe.\n"); return -1; } #ifndef RTPSEND if (isatty(STDOUT)) { e_printf("Standard output must be binded with pipe.\n"); return -1; } #endif /* ! RTPSEND */ if ((buffer = malloc(OPT.plen)) == NULL) { e_printf("cannot malloc for buffer\n"); return -1; } if (OPT.compatible_mode) { seq = 0; } else { srand(time(NULL)); seq = rand() & 0xffff; } d1_printf("first seq/rtp=%u\n",seq); rtp_reset(r_header, RTP_HEADER_LEN); rtp_set_version(r_header, 1); rtp_set_ptype(r_header, OPT.payload_type); memset(buffer, 0, OPT.plen); #ifdef RTPSEND switch(OPT.shaping_lev) { case 0: default: OPT.shaping_lev=0; waitperframe=1; d1_printf("shaping_mode : frame\n"); break; case 1: waitperframe=OPT.rs_N; d1_printf("shaping_mode : packet with dups\n"); break; case 2: waitperframe=OPT.rs_N*OPT.send_double; d1_printf("shaping_mode : all packet(include dups)\n"); break; } iov[0].iov_base = r_header; iov[0].iov_len = RTP_HEADER_LEN; iov[1].iov_base = buffer; /* iov[1].iov_len = OPT.plen;*/ #else /* RTPSEND */ iov[0].iov_base = p_header; iov[0].iov_len = PIPE_HEADER_LEN; iov[1].iov_base = r_header; iov[1].iov_len = RTP_HEADER_LEN; iov[2].iov_base = buffer; /* iov[2].iov_len = OPT.plen;*/ #endif /* RTPSEND */ p=pipe_context_init(STDIN,1 /*OPT.rs_N*/, OPT.plen); wclk_ps_tvstart.tv_sec=0; while ((length = pipe_blocked_read_packet_ex(p, p_header, buffer))>=0){ #ifdef RTPSEND if(wclk_ps_tvstart.tv_sec==0){ /* recode start time */ gettimeofday(&wclk_ps_tvstart, NULL); } count++; if(blk_wait4start){ gettimeofday(&blk_start_tv,NULL); blk_wait4start=0; blk_pktcnt = 0; }else{ blk_pktcnt++; } blk_wait4start=pipe_get_marker(p_header); #endif #ifdef RTPSEND iov[1].iov_len =length; pipe_set_length(p_header,length); #else iov[2].iov_len =length; pipe_set_length(p_header,length + RTP_HEADER_LEN); #endif /* RTPSEND*/ rtp_set_timestamp(r_header, pipe_get_timestamp(p_header)); rtp_set_marker(r_header, pipe_get_marker(p_header)); rtp_set_seqnum(r_header, seq++); if(seq>=0x10000) seq-=0x10000; d3_printf("rtpenc: marker %d : seq %d\n",pipe_get_marker(p_header),seq-1); #ifdef RTPSEND if (display_time_all_packet) { d_printf("\n%d:", seq); } rtsend_tslimit+=(u_int32_t)(pipe_get_timestamp(p_header) - pkt_tslast); pkt_tslast=pipe_get_timestamp(p_header); #if 0 wait4rtsend(&wclk_tvstart,blk_pktcnt); #else if(!(OPT.shaping_lev==0 && blk_pktcnt>=1)){ wait4rtsend(&wclk_tvstart,&rtsend_tslimit,blk_pktcnt,waitperframe); } #endif if (OPT.send_err_rate > 0) { if ((rand() % OPT.send_err_rate) == 0) { total_drop++; continue; } } d2_printf(" write %d bytes", pipe_get_length(p_header)); if (writev(OPT.sfd, iov, 2) == -1) { total_drop++; d2_printf(" writev-NG(ts/sq=%d/%d)\n", pipe_get_timestamp(p_header), count); } else { d2_printf(" writev-OK(ts/sq=%d/%d)\n", pipe_get_timestamp(p_header), count); total_send++; } if(OPT.dup2dummy){ rtp_set_seqnum(r_header, (seq+0x10000-0x100)&0xffff); } for(dummy_cnt=1;dummy_cnt<OPT.send_double;dummy_cnt++){ if(OPT.shaping_lev==2){ blk_pktcnt++; wait4rtsend(&wclk_tvstart,&rtsend_tslimit,blk_pktcnt,waitperframe); } d2_printf(" write dup(%d/%d) \n",dummy_cnt,OPT.send_double); io_ret=writev(OPT.sfd, iov, 2); if ( io_ret == -1) { total_drop++; d2_printf(" writev-NG(ts/sq=%d/%d)\n", pipe_get_timestamp(p_header), count); } else { d2_printf(" writev-OK(ts/sq=%d/%d)\n", pipe_get_timestamp(p_header), count); total_send++; } } #else /* RTPSEND */ d2_printf(" write pkt\n"); writev(STDOUT, iov, 3); if(OPT.dup2dummy){ rtp_set_seqnum(r_header, (seq+0x10000-0x100)&0xffff); } for(dummy_cnt=1;dummy_cnt<OPT.send_double;dummy_cnt++){ d2_printf(" write dup(%d/%d) \n",dummy_cnt,OPT.send_double); io_ret=writev(STDOUT, iov, 3); if(io_ret==-1){ exit_req=1; break; } } #endif /* RTPSEND */ if(exit_req==1){ break; } } #ifdef RTPSEND last_seq=seq-1; statistics_display(); sleep(1); #endif return 0; }