/* print_file_info() Display information about input and output files */ static void print_file_info( SNDFILE *inputfile, SF_INFO *sfinfo ) { SF_FORMAT_INFO format_info; SF_FORMAT_INFO subformat_info; char sndlibver[128]; char *duration = NULL; // Get the format format_info.format = sfinfo->format & SF_FORMAT_TYPEMASK; sf_command (inputfile, SFC_GET_FORMAT_INFO, &format_info, sizeof(format_info)) ; // Get the sub-format info subformat_info.format = sfinfo->format & SF_FORMAT_SUBMASK; sf_command (inputfile, SFC_GET_FORMAT_INFO, &subformat_info, sizeof(subformat_info)) ; // Get the version of libsndfile sf_command (NULL, SFC_GET_LIB_VERSION, sndlibver, sizeof(sndlibver)); // Get human readable duration of the input file duration = format_duration_string( sfinfo ); MAST_INFO( "---------------------------------------------------------"); MAST_INFO( "%s (http://www.mega-nerd.com/libsndfile/)", sndlibver); MAST_INFO( "Input File: %s", g_filename ); MAST_INFO( "Input Format: %s, %s", format_info.name, subformat_info.name ); MAST_INFO( "Input Sample Rate: %d Hz", sfinfo->samplerate ); if (sfinfo->channels == 1) MAST_INFO( "Input Channels: Mono" ); else if (sfinfo->channels == 2) MAST_INFO( "Input Channels: Stereo" ); else MAST_INFO( "Input Channels: %d", sfinfo->channels ); MAST_INFO( "Input Duration: %s", duration ); MAST_INFO( "---------------------------------------------------------"); free( duration ); }
// Crude way of automatically connecting up jack ports static void autoconnect_jack_ports( jack_client_t* client, int port_count ) { const char **all_ports; int ch=0, err = 0; int i; // Get a list of all the jack ports all_ports = jack_get_ports(client, NULL, NULL, JackPortIsOutput); if (!all_ports) { MAST_FATAL("autoconnect_jack_ports(): jack_get_ports() returned NULL"); } // Step through each port name for (i = 0; all_ports[i]; ++i) { const char* local_port = jack_port_name( g_jackport[ch] ); // Connect the port MAST_INFO("Connecting '%s' => '%s'", all_ports[i], local_port); err = jack_connect(client, all_ports[i], local_port); if (err != 0) MAST_FATAL("connect_jack_port(): failed to jack_connect() ports: %d", err); // Found enough ports ? if (++ch >= port_count) break; } free( all_ports ); }
/* oRTP callbacks */ static void ssrc_changed_cb(RtpSession *session) { MAST_INFO("The ssrc has changed"); /* reset the session */ rtp_session_reset( session ); }
void MastTool::set_session_address( const char* in_addr ) { char* address = strdup( in_addr ); char* portstr = NULL; int port = DEFAULT_RTP_PORT; // Look for port in the address portstr = strchr(address, '/'); if (portstr && strlen(portstr)>1) { *portstr = 0; portstr++; port = atoi(portstr); } // Make sure the port number is even if (port%2 == 1) port--; // Send of recieve address? if (this->session->mode == RTP_SESSION_RECVONLY) { // Set the local address/port if (rtp_session_set_local_addr( session, address, port )) { MAST_FATAL("Failed to set local address/port (%s/%d)", address, port); } else { MAST_INFO( "Local address: %s/%d", address, port ); } } else if (this->session->mode == RTP_SESSION_SENDONLY) { // Set the remote address/port if (rtp_session_set_remote_addr( session, address, port )) { MAST_FATAL("Failed to set remote address/port (%s/%d)", address, port); } else { MAST_INFO( "Remote address: %s/%d", address, port ); } } else { MAST_FATAL("Mode unsupported by MastTool: %d", this->session->mode); } free( address ); }
void MastSendTool::prepare() { // Display some information about the chosen payload type MAST_INFO( "Sending SSRC: 0x%x", session->snd.ssrc ); MAST_INFO( "Input Format: %d Hz, %s", samplerate, channels==2 ? "Stereo" : "Mono"); mimetype->print(); // Load the codec if (codec != NULL) MAST_WARNING("Codec has already been created" ); codec = MastCodec::new_codec( mimetype ); if (codec == NULL) MAST_FATAL("Failed to get create codec" ); MAST_INFO( "Output Format: %d Hz, %s", codec->get_samplerate(), codec->get_channels()==2 ? "Stereo" : "Mono"); // Work out the payload type to use if (strcmp("MPA", codec->get_type())==0) { // MPEG Audio is a special case this->set_payloadtype_index( RTP_MPEG_AUDIO_PT ); payloadtype->channels = codec->get_channels(); } else { // Ask oRTP for the index int index = ::rtp_profile_find_payload_number( profile, codec->get_type(), codec->get_samplerate(), codec->get_channels() ); if ( index<0 ) MAST_FATAL("Failed to get payload type information from oRTP"); this->set_payloadtype_index( index ); } // Calculate the packet size frames_per_packet = codec->frames_per_packet( payload_size_limit ); if (frames_per_packet<=0) MAST_FATAL( "Invalid number of samples per packet" ); // Create audio buffers input_buffer = new MastAudioBuffer( frames_per_packet, samplerate, channels ); if (input_buffer == NULL) MAST_FATAL("Failed to create audio input buffer"); //resampled_buffer = new MastAudioBuffer( frames_per_packet, codec->get_samplerate(), codec->get_channels() ); //if (resampled_buffer == NULL) MAST_FATAL("Failed to create resampled audio buffer"); // Allocate memory for the packet buffer payload_buffer = (u_int8_t*)malloc( payload_size_limit ); if (payload_buffer == NULL) MAST_FATAL("Failed to allocate memory for payload buffer"); }
void MastTool::set_payloadtype_index( int idx ) { // Lookup the payload type PayloadType* pt = rtp_profile_get_payload( profile, idx ); if (pt==NULL) MAST_WARNING("Failed to get payload type for index %d", idx); this->payloadtype = pt; // Store it this->payloadtype_index = idx; MAST_INFO( "Payload type index: %d", idx ); // Apply it to the session if (rtp_session_set_send_payload_type( session, idx )) { MAST_FATAL("Failed to set session payload type index"); } }
static void network_error_cb(RtpSession *session, const char* msg) { MAST_INFO("Network error: %s", msg); }
static void pt_changed_cb(RtpSession *session) { MAST_INFO("The payload type has changed"); }
// 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; }