static void parse_cmd_line(int argc, char **argv, MastSendTool* tool) { int ch; // Parse the options/switches while ((ch = getopt(argc, argv, "s:t:p:o:z:d:lh?")) != -1) switch (ch) { case 's': tool->set_session_ssrc( optarg ); break; case 't': tool->set_multicast_ttl( optarg ); break; case 'p': tool->set_payload_mimetype( optarg ); break; case 'o': tool->set_payload_mimetype_param( optarg ); break; case 'z': tool->set_payload_size_limit( optarg ); break; case 'd': tool->set_session_dscp( optarg ); break; case 'l': g_loop_file = TRUE; break; case '?': case 'h': default: usage(); } // Parse the ip address and port if (argc > optind) { tool->set_session_address( argv[optind++] ); } else { MAST_ERROR("missing address/port to send to"); usage(); } // Get the input file if (argc > optind) { g_filename = argv[optind++]; } else { MAST_ERROR("missing audio input filename"); usage(); } }
static void parse_cmd_line(int argc, char **argv, MastSendTool* tool) { int ch; // Parse the options/switches while ((ch = getopt(argc, argv, "as:t:p:o:z:d:c:r:h?")) != -1) switch (ch) { case 's': tool->set_session_ssrc( optarg ); break; case 't': tool->set_multicast_ttl( optarg ); break; case 'p': tool->set_payload_mimetype( optarg ); break; case 'o': tool->set_payload_mimetype_param( optarg ); break; case 'z': tool->set_payload_size_limit( optarg ); break; case 'd': tool->set_session_dscp( optarg ); break; case 'c': tool->set_input_channels( atoi(optarg) ); break; case 'a': g_do_autoconnect = TRUE; break; case 'r': g_rb_duration = atoi(optarg); break; case '?': case 'h': default: usage(); } // Parse the ip address and port if (argc > optind) { tool->set_session_address( argv[optind++] ); } else { MAST_ERROR("missing address/port to send to"); usage(); } }
/* Wait for an RTP packet to arrive and return it */ mblk_t *MastTool::wait_for_rtp_packet( int seconds ) { struct timeval timeout; fd_set readfds; int retval = -1; /* reset the session */ rtp_session_reset( session ); /* set the timeout */ timeout.tv_sec = seconds; timeout.tv_usec = 0; /* Watch socket to see when it has input */ FD_ZERO(&readfds); FD_SET( rtp_session_get_rtp_socket(session), &readfds); retval = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout); // Check return value if (retval == -1) { MAST_ERROR("select() failed: %s", strerror(errno)); return NULL; } else if (retval==0) { MAST_ERROR("Timed out waiting for packet after %d seconds", seconds); return NULL; } /* recieve packet and put it in queue */ rtp_session_rtp_recv( session, 0 ); /* check that there is something in the queue */ if (qempty(&session->rtp.rq) ) { MAST_ERROR("Queue is empty after trying to recieve packet"); return NULL; } /* take the packet off the queue and return it */ return getq(&session->rtp.rq); }
/* mast_fill_input_buffer() Make sure input buffer if full of audio */ size_t mast_fill_input_buffer( MastAudioBuffer* buffer ) { size_t total_read = 0; int frames_wanted = buffer->get_write_space(); int frames_read = 0; if (frames_wanted==0) { // No audio wanted MAST_DEBUG( "Tried to fill buffer when it is full" ); return 0; } // Loop until buffer is full while( frames_wanted > 0 ) { frames_wanted = buffer->get_write_space(); frames_read = sf_readf_float( g_input_file, buffer->get_write_ptr(), frames_wanted ); // Add on the frames read if (frames_read > 0) { buffer->add_frames( frames_read ); total_read += frames_read; } // Reached end of file? if (frames_read < frames_wanted) { MAST_DEBUG("Reached end of file (frames_wanted=%d, frames_read=%d)", frames_wanted, frames_read); if (g_loop_file) { // Seek back to the beginning if (sf_seek( g_input_file, 0, SEEK_SET )) { MAST_ERROR("Failed to seek to start of file: %s", sf_strerror( g_input_file ) ); return 0; } } else { // Reached end of file (and don't want to loop) break; } } } if (total_read == 0) { MAST_ERROR("Failed to read from file: %s", sf_strerror( g_input_file ) ); } return total_read; }
static void parse_cmd_line(int argc, char **argv, MastTool* tool) { int ch; // Parse the options/switches while ((ch = getopt(argc, argv, "h?")) != -1) switch (ch) { /* may still be useful for RTCP case 't': tool->set_multicast_ttl( optarg ); break; */ case '?': case 'h': default: usage(); } // Parse the ip address and port if (argc > optind) { tool->set_session_address( argv[optind++] ); } else { MAST_ERROR("missing address/port to send to"); usage(); } // Get the output file if (argc > optind) { g_filename = argv[optind++]; } else { MAST_ERROR("missing audio output filename"); usage(); } }
static void parse_cmd_line(int argc, char **argv, RtpSession* session) { char* local_address = NULL; int local_port = DEFAULT_RTP_PORT; int ch; // Parse the options/switches while ((ch = getopt(argc, argv, "h?")) != -1) switch (ch) { // case 'T': FIXME: timeout? case '?': case 'h': default: usage(); } // Parse the ip address and port if (argc > optind) { local_address = argv[optind]; optind++; // Look for port in the address char* portstr = strchr(local_address, '/'); if (portstr && strlen(portstr)>1) { *portstr = 0; portstr++; local_port = atoi(portstr); } } else { MAST_ERROR("missing address/port to receive from"); usage(); } // Make sure the port number is even if (local_port%2 == 1) local_port--; // Set the remote address/port if (rtp_session_set_local_addr( session, local_address, local_port )) { MAST_FATAL("Failed to set receive address/port (%s/%u)", local_address, local_port); } else { printf( "Receive address: %s/%u\n", local_address, local_port ); } }
int main(int argc, char **argv) { MastSendTool *tool = NULL; SF_INFO sfinfo; // Create the send tool object tool = new MastSendTool( MAST_TOOL_NAME ); tool->enable_scheduling(); // Parse the command line arguments // and configure the session parse_cmd_line( argc, argv, tool ); // Open the input file by filename memset( &sfinfo, 0, sizeof(sfinfo) ); g_input_file = sf_open(g_filename, SFM_READ, &sfinfo); if (g_input_file == NULL) MAST_FATAL("Failed to open input file:\n%s", sf_strerror(NULL)); tool->set_input_channels( sfinfo.channels ); tool->set_input_samplerate( sfinfo.samplerate ); // Display some information about the input file print_file_info( g_input_file, &sfinfo ); // Setup signal handlers mast_setup_signals(); // Run the main loop tool->run(); // Clean up delete tool; // Close input file if (sf_close( g_input_file )) { MAST_ERROR("Failed to close input file:\n%s", sf_strerror(g_input_file)); } // Success ! return 0; }
/* Take an hex SSRC string (from command line) and set it for session */ void MastTool::set_session_ssrc( const char* ssrc_str ) { int ssrc = 0; // Remove 0x from the start of the string if (optarg[0] == '0' && (optarg[1] == 'x' || optarg[1] == 'X')) { ssrc_str += 2; } // Parse the hexadecimal number into an integer if (sscanf(ssrc_str, "%x", &ssrc)<=0) { MAST_ERROR("SSRC should be a hexadeicmal number"); return; } // Set it in the session MAST_DEBUG( "SSRC for session set to 0x%x", ssrc ); rtp_session_set_ssrc( session, ssrc ); }
void MastSendTool::run() { // Set things up this->prepare(); // The main loop while( mast_still_running() ) { int frames_read = ::mast_fill_input_buffer( input_buffer ); int payload_bytes = 0; // Was there an error? if (frames_read < 0) break; // Encode audio payload_bytes = codec->encode_packet( input_buffer, payload_size_limit, payload_buffer ); if (payload_bytes<0) { MAST_ERROR("Codec encode failed" ); break; } // We used the audio up input_buffer->empty_buffer(); if (payload_bytes) { // Send out an RTP packet ::rtp_session_send_with_ts(session, payload_buffer, payload_bytes, ts); // Calculate the timestamp increment ts+=((frames_read * payloadtype->clock_rate) / codec->get_samplerate()); // * frames_per_packet; } } }
// Initialise Jack related stuff static jack_client_t* init_jack( MastSendTool* tool ) { const char* client_name = tool->get_tool_name(); jack_client_t* client = NULL; jack_status_t status; size_t ringbuffer_size = 0; int port_count = tool->get_input_channels(); int i = 0; pthread_mutex_init(&g_ringbuffer_cond_mutex, NULL); pthread_cond_init(&g_ringbuffer_cond, NULL); // Register with Jack if ((client = jack_client_open(client_name, g_client_opt, &status)) == 0) { MAST_ERROR("Failed to start jack client: 0x%x", status); return NULL; } else { MAST_INFO( "JACK client registered as '%s'", jack_get_client_name( client ) ); } // Create our input port(s) if (port_count==1) { if (!(g_jackport[0] = jack_port_register(client, "mono", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0))) { MAST_ERROR("Cannot register mono input port"); return NULL; } } else { if (!(g_jackport[0] = jack_port_register(client, "left", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0))) { MAST_ERROR("Cannot register left input port"); return NULL; } if (!(g_jackport[1] = jack_port_register(client, "right", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0))) { MAST_ERROR( "Cannot register left input port"); return NULL; } } // Create ring buffer ringbuffer_size = jack_get_sample_rate( client ) * g_rb_duration * port_count * sizeof(int16_t) / 1000; MAST_INFO("Duration of the ring buffer is %d ms (%d bytes)", g_rb_duration, (int)ringbuffer_size ); if (!(g_ringbuffer = jack_ringbuffer_create( ringbuffer_size ))) { MAST_ERROR("Cannot create ringbuffer %d", i); return NULL; } // Register callbacks jack_on_shutdown(client, shutdown_callback, tool ); jack_set_buffer_size_callback( client, buffersize_callback, tool); jack_set_process_callback(client, process_callback, tool); // Create conversion buffer buffersize_callback( jack_get_buffer_size(client), tool ); // Activate JACK if (jack_activate(client)) MAST_FATAL("Cannot activate JACK client"); /* Auto connect ports ? */ if (g_do_autoconnect) autoconnect_jack_ports( client, tool->get_input_channels() ); return client; }
int main(int argc, char **argv) { MastTool* tool = NULL; RtpProfile* profile = &av_profile; PayloadType* pt = NULL; FILE* output = NULL; mblk_t* packet = NULL; int ts_diff = 0; int ts = 0; // Create an RTP session tool = new MastTool( MAST_TOOL_NAME, RTP_SESSION_RECVONLY ); tool->enable_scheduling(); // Parse the command line arguments // and configure the session parse_cmd_line( argc, argv, tool ); // Recieve an initial packet packet = tool->wait_for_rtp_packet(); if (packet == NULL) MAST_FATAL("Failed to receive an initial packet"); // Lookup the payload type pt = rtp_profile_get_payload( profile, rtp_get_payload_type( packet ) ); if (pt == NULL) MAST_FATAL( "Payload type %d isn't registered with oRTP", rtp_get_payload_type( packet ) ); fprintf(stderr, "Payload type: %s\n", payload_type_get_rtpmap( pt )); // Work out the duration of the packet ts_diff = mast_rtp_packet_duration( packet ); MAST_DEBUG("ts_diff = %d", ts_diff); // Open the output file output = open_output_file( g_filename ); if (output==NULL) MAST_FATAL( "failed to open output file" ); // We can free the packet now freemsg( packet ); // Setup signal handlers mast_setup_signals(); // The main loop while( mast_still_running() ) { // Read in a packet packet = rtp_session_recvm_with_ts( tool->get_session(), ts ); if (packet==NULL) { MAST_DEBUG( "packet is NULL" ); } else { int data_len = mast_rtp_packet_size( packet ); if (data_len==0) { MAST_WARNING("Failed to get size of packet's payload"); } else { unsigned char* data_ptr = packet->b_cont->b_rptr; int bytes_written = 0; // Skip the extra header for MPA payload if (rtp_get_payload_type( packet ) == RTP_MPEG_AUDIO_PT) { data_ptr += 4; data_len -= 4; } // Update the timestamp difference ts_diff = mast_rtp_packet_duration( packet ); MAST_DEBUG("ts_diff = %d", ts_diff); MAST_DEBUG("data_len = %d", data_len); // Write to disk bytes_written = fwrite( data_ptr, 1, data_len, output ); if (bytes_written != data_len) { MAST_ERROR("Failed to write data to disk: %s", strerror(errno) ); break; } } } // Increment the timestamp for the next packet ts += ts_diff; } // Close output file if (fclose( output )) { MAST_ERROR("Failed to close output file:\n%s", strerror(errno)); } // Close RTP session delete tool; // Success return 0; }