Talker::MsgType Talker::receive_msg() { if (!receive()) return MSG_RESET; if (_rx_buffer[0] == '$') return receive_rtcp(); return receive_rtsp(); }
uint16_t RtpSession::receive_rtp_packet(void *buf ) { struct timeval start_time_tv; if ( ! m_preceived ) { /* This is the 1th packet that we receive- * Here we should send an RTCP SDES packet with all the * infos... */ gettimeofday(&start_time_tv, NULL); m_start_time = tv2dbl(start_time_tv); #if 0 /*! Build the SDES CNAME packet */ uint16_t s = 10 + strlen( m_cname ); /* Align to 32 bit boundary .. */ s = (uint16_t)ceil( (double)s /4 ) * 4; m_sdes_pkt = (rtcp_t *)calloc( s , 1 ); RtcpPacket *p = new RtcpPacket( m_sdes_pkt, s ); p->set_version( 2 ); p->set_padding( 0 ); p->set_count( 1 ); p->set_type( RTCP_SDES ); p->set_length( (uint16_t)s/4 - 1 ); m_sdes_pkt->r.sdes.src = htonl( m_ssrc ); m_sdes_pkt->r.sdes.item->type = RTCP_SDES_CNAME; m_sdes_pkt->r.sdes.item->length = strlen( m_cname ); memcpy( m_sdes_pkt->r.sdes.item[0].data, m_cname, strlen(m_cname) ); m_sdes_pkt_size = s; /*! Schedule an RTCP RR.. */ event_t *e = (event_t*)malloc( sizeof( event_t ) ); e->type = RTCP_RR; e->time = m_start_time + 5.0; e->next = NULL; insert_event( e ); send_rtcp(); #endif } int event = 0; int retval; double timeout, now; struct timeval timeout_tv, now_tv; fd_set sockets; /*! Here we check for events or things to do... */ while ( 1 ) { gettimeofday(&now_tv, NULL); now = tv2dbl(now_tv); if ( m_event_queue != NULL ) { event = 1; timeout = m_event_queue->time - now; } else { event = 0; timeout = 0.5; /* Arbitrary value.. to be trimmed.. */ } if ( timeout < 0 ) timeout = 0; timeout_tv = dbl2tv( timeout ); FD_ZERO( &sockets ); FD_SET( m_rtp_sock, &sockets ); FD_SET( m_rtcp_sock, &sockets ); int max_fd = ((m_rtp_sock > m_rtcp_sock) ? m_rtp_sock : m_rtcp_sock ) + 1; retval = select(max_fd, &sockets, NULL, NULL, &timeout_tv); if ( retval < 0 ) { perror("select"); return false; } else if ( retval > 0 ) { // There are some events... if (FD_ISSET(m_rtp_sock, &sockets)) { /* There's an RTP packet to be read... */ return receive_rtp( buf ); } if (FD_ISSET(m_rtcp_sock, &sockets)) { receive_rtcp(); } } else { /* retval == 0, select timed out */ if (event) { gettimeofday( &now_tv, NULL ); now = tv2dbl( now_tv ); while ( m_event_queue != NULL && m_event_queue->time <= now ) { /* There is a pending RTCP packet to send) */ send_rtcp(); } } } } }
bool RtpSession::send_rtp_packet(void *buf, uint16_t size, uint32_t ts_inc ) { uint32_t timestamp; struct timeval start_time_tv, now_tv; double play_time, now; timestamp = m_prev_timestamp + ts_inc; m_prev_timestamp = timestamp; if ( !buf || !size ) { printf("Cannot send packet.\n"); return false; } if ( ! m_psent ) { /* This is the 1th packet that we send. * Here we should send an RTCP SDES packet with all the * infos... */ gettimeofday(&start_time_tv, NULL); m_start_time = tv2dbl(start_time_tv); /*! Build the SDES CNAME packet */ uint16_t s = 10 + strlen( m_cname ); /* Align to 32 bit boundary .. */ s = (uint16_t)ceil( (double)s /4 ) * 4; m_sdes_pkt = (rtcp_t *)calloc( s , 1 ); RtcpPacket *p = new RtcpPacket( m_sdes_pkt, s ); p->set_version( 2 ); p->set_padding( 0 ); p->set_count( 1 ); p->set_type( RTCP_SDES ); p->set_length( (uint16_t)s/4 - 1 ); m_sdes_pkt->r.sdes.src = htonl( m_ssrc ); m_sdes_pkt->r.sdes.item->type = RTCP_SDES_CNAME; m_sdes_pkt->r.sdes.item->length = strlen( m_cname ); memcpy( m_sdes_pkt->r.sdes.item[0].data, m_cname, strlen(m_cname) ); m_sdes_pkt_size = s; /*! Schedule an RTCP for now.. */ event_t *e = (event_t*)malloc( sizeof( event_t ) ); e->type = RTCP_SR; e->time = 0.0; e->next = NULL; insert_event( e ); send_rtcp(); } /** OK, we build the real RTP packet... */ RtpPacket *pkt = new RtpPacket( (uint8_t*)buf, size ); pkt->set_ssrc( m_ssrc ); pkt->set_payload_type( m_payload_type ); pkt->set_sequence( m_seq++ ); pkt->set_timestamp( timestamp ); delete pkt; if ( ! send_pkt( buf, size ) ) { /* Problems sending packet.. probably the client closed * the connection.. */ return false; } /* *************************************************** */ /*! Here we check for events or things to do... */ /* Schedule the times to play packets as an absolute offset from * our start time, rather than a relative offset from the initial * packet. (We're less vulnerable to drifting clocks that way). * Alternative version based on timestamps and RTP clock.. */ play_time = m_start_time + ((double)(timestamp - m_base_timestamp)/ m_rtp_clock); // printf("play_time: %f - difference: %f sec.\n", play_time, // ((double)(timestamp - m_base_timestamp)/ m_rtp_clock)); while (gettimeofday(&now_tv, NULL), (now = tv2dbl(now_tv)) < play_time) { int event = 0; int retval; double timeout; struct timeval timeout_tv; fd_set sockets; if ( m_event_queue != NULL && m_event_queue->time < play_time ) { event = 1; timeout = m_event_queue->time - now; } else { event = 0; timeout = play_time - now; } if ( timeout < 0 ) timeout = 0; timeout_tv = dbl2tv( timeout ); FD_ZERO( &sockets ); FD_SET( m_rtp_sock, &sockets ); FD_SET( m_rtcp_sock, &sockets ); int max_fd = ((m_rtp_sock > m_rtcp_sock) ? m_rtp_sock : m_rtcp_sock ) + 1; retval = select(max_fd, &sockets, NULL, NULL, &timeout_tv); if ( retval < 0 ) { perror("select"); exit(1); } else if ( retval > 0 ) { // There are some events... if (FD_ISSET(m_rtp_sock, &sockets)) { /* There's an RTP packet to be read... * We should receive, validate and .. trash it.. */ receive_rtp( (void*)m_buf ); } if (FD_ISSET(m_rtcp_sock, &sockets)) { receive_rtcp(); } } else { /* retval == 0, select timed out */ if (event) { gettimeofday( &now_tv, NULL ); now = tv2dbl( now_tv ); while ( m_event_queue != NULL && m_event_queue->time <= now ) { /* There is a pending RTCP packet to send) */ send_rtcp(); } } else break; /* Time for the next packet */ } } /* **************************************************** */ return true; }