Beispiel #1
0
/*
  mast_fill_input_buffer()
  Make sure input buffer if full of audio  
*/
size_t mast_fill_input_buffer( MastAudioBuffer* buffer )
{
	int frames_wanted = buffer->get_write_space();
	size_t bytes_wanted = frames_wanted * buffer->get_channels() * sizeof( mast_sample_t );
	size_t bytes_read = 0, frames_read = 0;



	// Keep checking that there is enough audio available
	while (jack_ringbuffer_read_space(g_ringbuffer) < bytes_wanted) {
		MAST_WARNING( "Not enough audio available in ringbuffer; waiting" );
		//MAST_DEBUG("Ring buffer is %u%% full", (jack_ringbuffer_read_space(g_ringbuffer)*100) / g_ringbuffer->size);

		// Wait for some more audio to become available
		pthread_mutex_lock(&g_ringbuffer_cond_mutex);
		pthread_cond_wait(&g_ringbuffer_cond, &g_ringbuffer_cond_mutex);
		pthread_mutex_unlock(&g_ringbuffer_cond_mutex);
	}

	// Copy frames from ring buffer to temporary buffer
	bytes_read = jack_ringbuffer_read(g_ringbuffer, (char*)buffer->get_write_ptr(), bytes_wanted);
	if (bytes_read<=0) MAST_FATAL( "Failed to read from ringbuffer" );
	if (bytes_read!=bytes_wanted) MAST_WARNING("Failed to read enough audio for a full packet");
	
	// Mark the space in the buffer as used
	frames_read = bytes_read / (buffer->get_channels() * sizeof( mast_sample_t ));
	buffer->add_frames( frames_read );

	// Return the number 
	return frames_read;
}
Beispiel #2
0
// Initialise the codec
MastCodec_MPA::MastCodec_MPA( MastMimeType *type)
	: MastCodec(type)
{

	// Set default values
	this->samplerate = MPA_DEFAULT_SAMPLERATE;
	this->channels = MPA_DEFAULT_CHANNELS;


	// Initialise twolame
	this->twolame = twolame_init();
	if (this->twolame==NULL) {
		MAST_FATAL( "Failed to initialise TwoLame" );
	}

	// Configure twolame
	if (twolame_set_num_channels( this->twolame, this->channels )) {
		MAST_WARNING( "Failed to set number of input channels" );
	}
	if (twolame_set_in_samplerate( this->twolame, this->samplerate )) {
		MAST_WARNING( "Failed to set number of input samplerate" );
	}
	
	
	// Apply MIME type parameters to the codec
	this->apply_mime_type_params( type );

	
	// Get TwoLAME ready to go...
	twolame_init_params( this->twolame );

}
Beispiel #3
0
// Callback called by JACK when jackd is shutting down
static void shutdown_callback(void *arg)
{
	MAST_WARNING("MAST quitting because jackd is shutting down" );
	
	// Signal the main thead to stop
	mast_stop_running();
}
Beispiel #4
0
void MastTool::set_payload_size_limit( char const* size_limit_str )
{
	int size_limit = atoi( size_limit_str );
	
	if (size_limit <= 1) MAST_WARNING( "Invalid payload size: %d", size_limit);

	this->payload_size_limit = size_limit;
}
Beispiel #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;
}
Beispiel #6
0
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");
	}
}
Beispiel #7
0
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");

}
Beispiel #8
0
// Shut down jack related stuff
static void deinit_jack( jack_client_t *client )
{
	// Leave the Jack graph
	if (jack_client_close(client)) {
		MAST_WARNING("Failed to close jack client");
	}
	
	// Free the coversion buffer
	if (g_interleavebuf) {
		free( g_interleavebuf );
		g_interleavebuf = NULL;
	}
	
	// Free up the ring buffer
	if (g_ringbuffer) {
		jack_ringbuffer_free( g_ringbuffer );
		g_ringbuffer = NULL;
	}

    pthread_cond_destroy(&g_ringbuffer_cond);
    pthread_mutex_destroy(&g_ringbuffer_cond_mutex);

}
Beispiel #9
0
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;
}
Beispiel #10
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;
}