Beispiel #1
0
void TransportCCRTP::flush()
{
	if( sendBuffer->getReadyCount() > 0 ) {
		uint32 current_timestamp = socket->getCurrentTimestamp();
		//printf("%ld %ld\n", current_timestamp, timestamp);
		//fprintf(out1, "%ld\n", current_timestamp);
		//fprintf(out2, "%ld\n", timestamp);
		if(seq32_t(timestamp) <= seq32_t(current_timestamp + framesPerPacket)) {
			socket->setExpireTimeout(frameSize*framesPerPacket * 1000);
			char *buf;
			int length = sendBuffer->peekMessage(&buf);
			socket->putData(timestamp, (unsigned char*)buf, length);
			sendBuffer->skipMessage();
			timestamp += framesPerPacket;
		} else {
			//printf("discarding surplus of audio samples, current timestamp: %ld, timestamp: %ld\n",
				//current_timestamp, timestamp); fflush(stdout);
		}

		if(current_timestamp > timestamp+2000)
			timestamp = socket->getCurrentTimestamp();
	}
	sendBuffer->debug();
}
Beispiel #2
0
// NOTE: no operations on the phone object are allowed inside the run() method.
//       Such an operation needs a lock on the transaction layer. The destructor
//       on audio_rx is called while this lock is locked. The destructor waits
//	 in a busy loop for the run() method to finish. If the run() method would
//       need the phone lock, this would lead to a dead lock (and a long trip
//	 in debug hell!)
void t_audio_rx::run(void) {
	//struct timeval debug_timer;
	unsigned short sound_payload_size;
	uint32 dtmf_rtp_timestamp;
	
	phone->add_prohibited_thread();
	ui->add_prohibited_thread();
	
	// This flag indicates if we are currently in a silence period.
	// The start of a new stream is assumed to start in silence, such
	// that the very first RTP packet will be marked.
	bool silence_period = true;
	uint64 silence_nsamples = 0; // duration in samples
	
	// This flag indicates if a sound frame can be suppressed
	bool suppress_samples = false;

	// The running flag is set already in t_audio_session::run to prevent
	// a crash when the thread gets destroyed before it starts running.
	// is_running = true;

	// For a 3-way conference only the main receiver has access
	// to the dsp.
	if (!is_3way || is_main_rx_3way) {
		// Enable recording
		if (sys_config->equal_audio_dev(sys_config->get_dev_speaker(),
				sys_config->get_dev_mic())) 
		{
			input_device->enable(true, true);
		} else {
			input_device->enable(false, true);
		}

		// If the stream is stopped for call-hold, then the buffer might
		// be filled with old sound samples.
		input_device->flush(false, true);
	}

	// Synchronize the timestamp driven by the sampling rate
	// of the recording with the timestamp of the RTP session.
	// As the RTP session is already created in advance, the
	// RTP clock is a bit ahead already.
	timestamp = rtp_session->getCurrentTimestamp() + nsamples;

	// This loop keeps running until the stop_running flag is set to true.
	// When a call is being released the stop_running flag is set to true.
	// At that moment the lock on the transaction layer (phone) is taken.
	// So do not use operations that take the phone lock, otherwise a
	// dead lock may occur during call release.
	while (true) {
		if (stop_running) break;

		if (dtmf_player) {
			rtp_session->setMark(false);
			// Skip samples from sound card
			input_device->read(input_sample_buf, SAMPLE_BUF_SIZE);
			sound_payload_size = dtmf_player->get_payload(
				payload, payload_size, timestamp, dtmf_rtp_timestamp);
			silence_period = false;
		} else if (get_dtmf_event()) {
			// RFC 2833
			// Set marker in first RTP packet of a DTMF event
			rtp_session->setMark(true);
			// Skip samples from sound card
			input_device->read(input_sample_buf, SAMPLE_BUF_SIZE);
			assert(dtmf_player);
			sound_payload_size = dtmf_player->get_payload(
				payload, payload_size, timestamp, dtmf_rtp_timestamp);
			silence_period = false;
		} else if (get_sound_samples(sound_payload_size, suppress_samples)) {
			if (suppress_samples && use_nat_keepalive) {
				if (!silence_period) silence_nsamples = 0;
				
				// Send a silence packet at the NAT keep alive interval
				// to keep the NAT bindings for RTP fresh.
				silence_nsamples += SAMPLE_BUF_SIZE / 2;
				if (silence_nsamples > 
					(uint64_t)user_config->get_timer_nat_keepalive() * 1000 *
					audio_encoder->get_sample_rate())
				{
					suppress_samples = false;
				}
			}
		
			if (silence_period && !suppress_samples) {
				// RFC 3551 4.1
				// Set marker bit in first RTP packet after silence
				rtp_session->setMark(true);
			} else {
				rtp_session->setMark(false);
			}
			silence_period = suppress_samples;
		} else {
			continue;
		}

		// If timestamp is more than 1 payload size ahead of the clock of
		// the ccRTP stack, then drop the current payload and do not advance
		// the timestamp. This will happen if the DSP delivers more
		// sound samples than the set sample rate. To compensate for this
		// samples must be dropped.
		uint32 current_timestamp = rtp_session->getCurrentTimestamp();
		if (seq32_t(timestamp) <= seq32_t(current_timestamp + nsamples)) {
			if (dtmf_player) {
				// Send DTMF payload
				rtp_session->putData(dtmf_rtp_timestamp, payload,
							sound_payload_size);

				// If DTMF has ended then set payload back to sound
				if (dtmf_player->finished()) {
					set_sound_payload_format();
					MEMMAN_DELETE(dtmf_player);
					delete dtmf_player;
					dtmf_player = NULL;
				}
			} else if (!suppress_samples) {
				// Send sound samples
				// Set the expire timeout to the jitter buffer size.
				// This allows for old packets still to be sent out.
				rtp_session->setExpireTimeout(MAX_OUT_AUDIO_DELAY_MS * 1000);
				rtp_session->putData(timestamp, payload, sound_payload_size);
			}

			timestamp += nsamples;
		} else {
			log_file->write_header("t_audio_rx::run", LOG_NORMAL, LOG_DEBUG);
			log_file->write_raw("Audio rx line ");
			log_file->write_raw(get_line()->get_line_number()+1);
			log_file->write_raw(": discarded surplus of sound samples.\n");
			log_file->write_raw("Timestamp: ");
			log_file->write_raw(timestamp);
			log_file->write_endl();
			log_file->write_raw("Current timestamp: ");
			log_file->write_raw(current_timestamp);
			log_file->write_endl();
			log_file->write_raw("nsamples: ");
			log_file->write_raw(nsamples);
			log_file->write_endl();
			log_file->write_footer();
		}

		// If there is enough data in the DSP buffers to fill another
		// RTP packet then do not sleep, but immediately go to the
		// next cycle to play out the data. Probably this thread did
		// not get enough time, so the buffer filled up. The far end
		// jitter buffer has to cope with the jitter caused by this.
		if (is_3way && !is_main_rx_3way) {
			if (media_3way_peer_rx->size_content() >= SAMPLE_BUF_SIZE) {
				continue;
			}
		} else {
			if (input_device->get_buffer_space(true) >= SAMPLE_BUF_SIZE) continue;
		}

		// There is no data left in the DSP buffers to play out anymore.
		// So the timestamp must be in sync with the clock of the ccRTP
		// stack. It might get behind if the sound cards samples a bit
		// slower than the set sample rate. Advance the timestamp to get
		// in sync again.
		current_timestamp = rtp_session->getCurrentTimestamp();
		if (seq32_t(timestamp) <= seq32_t(current_timestamp - 
			(JITTER_BUF_MS / audio_encoder->get_ptime()) * nsamples))
		{
			timestamp += nsamples * (JITTER_BUF_MS / audio_encoder->get_ptime());
			log_file->write_header("t_audio_rx::run", LOG_NORMAL, LOG_DEBUG);
			log_file->write_raw("Audio rx line ");
			log_file->write_raw(get_line()->get_line_number()+1);
			log_file->write_raw(": timestamp forwarded by ");
			log_file->write_raw(nsamples * (JITTER_BUF_MS /
					audio_encoder->get_ptime()));
			log_file->write_endl();
			log_file->write_raw("Timestamp: ");
			log_file->write_raw(timestamp);
			log_file->write_endl();
			log_file->write_raw("Current timestamp: ");
			log_file->write_raw(current_timestamp);
			log_file->write_endl();
			log_file->write_raw("nsamples: ");
			log_file->write_raw(nsamples);
			log_file->write_endl();
			log_file->write_footer();
		}			
	}

	phone->remove_prohibited_thread();
	ui->remove_prohibited_thread();
	is_running = false;
}