示例#1
0
// Calculate the number of samples per packet
size_t MastCodec_MPA::frames_per_packet_internal( size_t max_bytes )
{
	int frames_per_packet = max_bytes/twolame_get_framelength( this->twolame );
	MAST_DEBUG("MPEG Audio Frames per Packet: %d", frames_per_packet );
	
	return frames_per_packet*TWOLAME_SAMPLES_PER_FRAME;
}
示例#2
0
/*
  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;
}
示例#3
0
// Constructors
MastTool::MastTool( const char* tool_name, RtpSessionMode mode )
{
	int log_level = ORTP_WARNING|ORTP_ERROR|ORTP_FATAL;


	// Initialise defaults
	this->session = NULL;
	this->profile = &av_profile;
	this->mimetype = new MastMimeType();
	this->payloadtype = NULL;
	this->payloadtype_index = -1;
	this->tool_name = tool_name;
	this->payload_size_limit = DEFAULT_PAYLOAD_LIMIT;


	// Initialise the oRTP library
	ortp_init();

	
	// Set the logging message level
#ifdef DEBUGGING
	MAST_DEBUG( "Compiled with debugging enabled" );
	log_level |= ORTP_DEBUG;
	log_level |= ORTP_MESSAGE;
#endif	
	ortp_set_log_level_mask(log_level);


	// Create RTP session
	session = rtp_session_new( mode );
	if (session==NULL) {
		MAST_FATAL( "Failed to create oRTP session.\n" );	
	}

	// Enabled multicast loopback
	rtp_session_set_multicast_loopback(session, TRUE);

	// Callbacks
	rtp_session_signal_connect(session,"ssrc_changed",(RtpCallback)ssrc_changed_cb, 0);
	rtp_session_signal_connect(session,"payload_type_changed",(RtpCallback)pt_changed_cb, 0);
	rtp_session_signal_connect(session,"network_error",(RtpCallback)network_error_cb, 0);


	// Set the MPEG Audio payload type to 14 in the AV profile
	rtp_profile_set_payload(profile, RTP_MPEG_AUDIO_PT, &payload_type_mpeg_audio);


	// Set RTCP parameters
	this->set_source_sdes();

}
示例#4
0
// Callback called by JACK when buffersize changes
static int buffersize_callback(jack_nframes_t nframes, void *arg)
{
	MastSendTool* tool = (MastSendTool*)arg;
	int channels = tool->get_input_channels();
	MAST_DEBUG("JACK buffer size is %d samples long", nframes);

	// (re-)allocate conversion buffer
	g_interleavebuf = (jack_default_audio_sample_t*)
		realloc( g_interleavebuf, nframes * sizeof(float) * channels );
	if (g_interleavebuf == NULL) {
		MAST_FATAL("Failed to (re-)allocate the convertion buffer");
	}

	// Success
	return 0;
}
示例#5
0
int MastCodec_MPA::set_param_internal( const char* name, const char* value )
{

	/*	Parameters listed in RFC3555 for audio/MPA:
	
		layer: 1,2,3
		samplerate: 
		mode: "stereo", "joint_stereo", "single_channel", "dual_channel"
		bitrate: the data rate for the audio bit stream
		ptime: duration of each packet in milliseconds
		maxptime: maximum duration of each packet in milliseconds
		
		Example:
		audio/MPA;layer=2;mode=stereo;bitrate=160;
	*/
	
	if (strcmp(name, "layer")==0) {
		int layer = atoi(value);
		if (layer!=2) return -2;
	} else if (strcmp(name, "mode")==0) {
		TWOLAME_MPEG_mode mode;
		if (strcmp(value, "stereo")==0) mode = TWOLAME_STEREO;
		else if (strcmp(value, "joint_stereo")==0) mode = TWOLAME_JOINT_STEREO;
		else if (strcmp(value, "single_channel")==0) mode = TWOLAME_MONO;
		else if (strcmp(value, "dual_channel")==0) mode = TWOLAME_DUAL_CHANNEL;
		else return -2;
		
		if (twolame_set_mode( this->twolame, mode )) {
			MAST_WARNING("Failed to set mode");
		}
	} else if (strcmp(name, "bitrate")==0) {
		int bitrate = atoi(value);
		if (twolame_set_bitrate( this->twolame, bitrate )) {
			MAST_WARNING("Failed to set bitrate");
		} else {
			MAST_DEBUG("Set bitrate to %d", bitrate);
		}
	} else {
		// Unsupported parameter
		return -1;
	}
	
	// Success
	return 0;
}
示例#6
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 );

}
示例#7
0
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;
}