/***************************************************************************** * udp_Read *****************************************************************************/ block_t *udp_Read( mtime_t i_poll_timeout ) { struct pollfd pfd[2]; int i_ret, i_nb_fd = 1; pfd[0].fd = i_handle; pfd[0].events = POLLIN; if ( i_comm_fd != -1 ) { pfd[1].fd = i_comm_fd; pfd[1].events = POLLIN; i_nb_fd++; } i_ret = poll( pfd, i_nb_fd, (i_poll_timeout + 999) / 1000 ); i_wallclock = mdate(); if ( i_ret < 0 ) { if( errno != EINTR ) msg_Err( NULL, "couldn't poll from socket (%s)", strerror(errno) ); return NULL; } if ( pfd[0].revents ) { struct iovec p_iov[i_block_cnt + 1]; block_t *p_ts, **pp_current = &p_ts; int i_iov, i_block; ssize_t i_len; uint8_t p_rtp_hdr[RTP_HEADER_SIZE]; if ( !i_last_packet ) { switch (i_print_type) { case PRINT_XML: printf("<STATUS type=\"lock\" status=\"1\"/>\n"); break; default: printf("frontend has acquired lock\n" ); } } i_last_packet = i_wallclock; if ( !b_udp ) { /* FIXME : this is wrong if RTP header > 12 bytes */ p_iov[0].iov_base = p_rtp_hdr; p_iov[0].iov_len = RTP_HEADER_SIZE; i_iov = 1; } else i_iov = 0; for ( i_block = 0; i_block < i_block_cnt; i_block++ ) { *pp_current = block_New(); p_iov[i_iov].iov_base = (*pp_current)->p_ts; p_iov[i_iov].iov_len = TS_SIZE; pp_current = &(*pp_current)->p_next; i_iov++; } pp_current = &p_ts; if ( (i_len = readv( i_handle, p_iov, i_iov )) < 0 ) { msg_Err( NULL, "couldn't read from network (%s)", strerror(errno) ); goto err; } if ( !b_udp ) { uint8_t pi_new_ssrc[4]; if ( !rtp_check_hdr(p_rtp_hdr) ) msg_Warn( NULL, "invalid RTP packet received" ); if ( rtp_get_type(p_rtp_hdr) != RTP_TYPE_TS ) msg_Warn( NULL, "non-TS RTP packet received" ); rtp_get_ssrc(p_rtp_hdr, pi_new_ssrc); if ( !memcmp( pi_ssrc, pi_new_ssrc, 4 * sizeof(uint8_t) ) ) { if ( rtp_get_seqnum(p_rtp_hdr) != i_seqnum ) msg_Warn( NULL, "RTP discontinuity" ); } else { struct in_addr addr; memcpy( &addr.s_addr, pi_new_ssrc, 4 * sizeof(uint8_t) ); msg_Dbg( NULL, "new RTP source: %s", inet_ntoa( addr ) ); memcpy( pi_ssrc, pi_new_ssrc, 4 * sizeof(uint8_t) ); switch (i_print_type) { case PRINT_XML: printf("<STATUS type=\"source\" source=\"%s\"/>\n", inet_ntoa( addr )); break; default: printf("new RTP source: %s\n", inet_ntoa( addr ) ); } } i_seqnum = rtp_get_seqnum(p_rtp_hdr) + 1; i_len -= RTP_HEADER_SIZE; } i_len /= TS_SIZE; while ( i_len && *pp_current ) { pp_current = &(*pp_current)->p_next; i_len--; } i_wallclock = mdate(); err: block_DeleteChain( *pp_current ); *pp_current = NULL; return p_ts; } else if ( i_last_packet && i_last_packet + UDP_LOCK_TIMEOUT < i_wallclock ) { switch (i_print_type) { case PRINT_XML: printf("<STATUS type=\"lock\" status=\"0\"/>\n"); break; default: printf("frontend has lost lock\n" ); } i_last_packet = 0; } if ( i_comm_fd != -1 && pfd[1].revents ) comm_Read(); return NULL; }
int main(int argc, char **argv) { MastTool* tool = NULL; mblk_t* packet = NULL; mblk_t* body = NULL; PayloadType* pt = NULL; int payload_size = 0; // Create an RTP session tool = new MastTool( MAST_TOOL_NAME, RTP_SESSION_RECVONLY ); if (tool==NULL) return -1; // Parse the command line arguments // and configure the session parse_cmd_line( argc, argv, tool->get_session() ); // Setup signal handlers mast_setup_signals(); // Recieve a single packet packet = tool->wait_for_rtp_packet(); if (packet == NULL) MAST_FATAL("Failed to receive a packet"); body = packet->b_cont; payload_size = (body->b_wptr - body->b_rptr); // Display information about the packet received printf("\n"); printf("RTP Header\n"); printf("==========\n"); printf("Payload type : %u\n", rtp_get_payload_type( packet ) ); printf("Payload size : %u bytes\n", payload_size ); printf("Sequence Number : %u\n", rtp_get_seqnumber( packet ) ); printf("Timestamp : %u\n", rtp_get_timestamp( packet ) ); printf("SSRC Identifier : %x\n", rtp_get_ssrc( packet ) ); printf("Marker Bit : %s\n", rtp_get_markbit( packet ) ? "Set" : "Not Set"); printf("\n"); // Lookup the payload type pt = rtp_profile_get_payload( tool->get_profile(), rtp_get_payload_type( packet ) ); if (pt == NULL) { MAST_WARNING( "Payload type %u isn't registered with oRTP", rtp_get_payload_type( packet ) ); } else { const char* mime_major = "?"; printf("Payload Details\n"); printf("===============\n"); if (pt->type==PAYLOAD_AUDIO_CONTINUOUS) mime_major = "audio"; else if (pt->type==PAYLOAD_AUDIO_PACKETIZED) mime_major = "audio"; else if (pt->type==PAYLOAD_VIDEO) mime_major = "video"; printf("Mime Type : %s/%s\n", mime_major, pt->mime_type); if (pt->clock_rate) printf("Clock Rate : %u Hz\n", pt->clock_rate); if (pt->channels) printf("Channels : %u\n", pt->channels); if (pt->bits_per_sample) printf("Bits per Sample : %u\n", pt->bits_per_sample); if (pt->normal_bitrate) { printf("Normal Bitrate : %u kbps\n", (pt->normal_bitrate/1000)); printf("Packet duration : %u ms\n", (payload_size*1000)/(pt->normal_bitrate/8) ); } if (pt->recv_fmtp) printf("Recieve FMTP : %s\n", pt->recv_fmtp); if (pt->send_fmtp) printf("Send FMTP : %s\n", pt->send_fmtp); printf("\n"); } // Parse the MPEG Audio header if (rtp_get_payload_type( packet ) == RTP_MPEG_AUDIO_PT) { /* FIXME: check fragment offset header (see rfc2250) */ unsigned char* mpa_ptr = body->b_rptr + 4; MPA_Header mh; printf("MPEG Audio Header\n"); printf("=================\n"); if (!mh.parse( mpa_ptr )) { MAST_WARNING("Failed to parse MPEG Audio header"); } else { mh.debug( stdout ); } } // Close RTP session delete tool; // Success ! return 0; }