Example #1
0
/* add silence to RTP stream from last packet time to current time which is in header->ts */
void
RTP::jt_tail(struct pcap_pkthdr *header) {

	if(!ast_jb_test(channel_record)) {
		// there is no ongoing recording, return
		return;
	}

	/* protect for endless loops (it cannot happen in theory but to be sure */
	if(packetization <= 0) {
		Call *owner = (Call*)call_owner;
		if(owner) {
			syslog(LOG_ERR, "call-id[%s]: packetization is 0 in jitterbuffer function.", owner->get_fbasename_safe());
		} else {
			syslog(LOG_ERR, "call-id[N/A]: packetization is 0 in jitterbuffer function.");
		}
		return;
	}

	/* calculate time difference between last packet and current packet + packetization time*/ 
	if(channel_record->last_ts.tv_sec == 0) {
		// previouuse tv_sec is not set, set it
		memcpy(&channel_record->last_ts, &header->ts, sizeof(timeval));
		return;
	}
	int msdiff = ast_tvdiff_ms(header->ts, channel_record->last_ts);
	msdiff -= packetization;

	while( msdiff >= packetization )  {
		ast_jb_get_and_deliver(channel_record, &channel_record->last_ts);
		/* adding packetization time to last_ts time */ 
		struct timeval tmp = ast_tvadd(channel_record->last_ts, ast_samp2tv(packetization, 1000));
		memcpy(&channel_record->last_ts, &tmp, sizeof(struct timeval));
		msdiff -= packetization;
	}
}
Example #2
0
/* simulate jitterbuffer */
void
RTP::jitterbuffer(struct ast_channel *channel, int savePayload) {

	if(codec == PAYLOAD_TELEVENT) return;

	Call *owner = (Call*)call_owner;
	if(owner and savePayload and owner->silencerecording) {
		// skip recording 
		frame->skip = 1;
	} else {
		frame->skip = 0;
	}
	struct timeval tsdiff;
	switch(codec) {
		case PAYLOAD_OPUS12:
			frame->ts = getTimestamp() / 12;
			frame->len = packetization * 2 / 3;
			break;
		case PAYLOAD_ISAC16:
		case PAYLOAD_SILK16:
		case PAYLOAD_OPUS16:
			frame->ts = getTimestamp() / 16;
			frame->len = packetization / 2;
			break;
		case PAYLOAD_SILK24:
		case PAYLOAD_OPUS24:
			frame->ts = getTimestamp() / 24;
			frame->len = packetization / 3;
			break;
		case PAYLOAD_OPUS48:
			frame->ts = getTimestamp() / 48;
			frame->len = packetization / 6;
			break;
		default: 
			frame->ts = getTimestamp() / 8;
			frame->len = packetization;
	}
	frame->marker = getMarker();
	frame->seqno = getSeqNum();
	channel->codec = codec;
	memcpy(&frame->delivery, &header->ts, sizeof(struct timeval));

	/* protect for endless loops (it cannot happen in theory but to be sure */
	if(packetization <= 0) {
		if(pinformed == 0) {
			if(owner) {
				syslog(LOG_ERR, "call-id[%s] ssrc[%x]: packetization is 0 in jitterbuffer function.", owner->get_fbasename_safe(), getSSRC());
				
			} else {
				syslog(LOG_ERR, "call-id[N/A] ssrc[%x]: packetization is 0 in jitterbuffer function.", getSSRC());
			}
		}
		pinformed = 1;
		return;
	} else {
		pinformed = 0;
	}

	struct iphdr2 *header_ip = (struct iphdr2 *)(data - sizeof(struct iphdr2) - sizeof(udphdr2));
	int mylen = MIN(len, ntohs(header_ip->tot_len) - header_ip->ihl * 4 - sizeof(udphdr2));


	if(savePayload or (codec == PAYLOAD_G729 or codec == PAYLOAD_G723)) {
		/* get RTP payload header and datalen */
		payload_data = data + sizeof(RTPFixedHeader);
		payload_len = mylen - sizeof(RTPFixedHeader);
		if(getPadding()) {
			/*
			* If set, this packet contains one or more additional padding
			* bytes at the end which are not part of the payload. The last
			* byte of the padding contains a count of how many padding bytes
			* should be ignored. Padding may be needed by some encryption
			* algorithms with fixed block sizes or for carrying several RTP
			* packets in a lower-layer protocol data unit.
			*/
			payload_len -= ((u_int8_t *)data)[payload_len - 1];
		}
		if(getCC() > 0) {
			/*
			* The number of CSRC identifiers that follow the fixed header.
			*/
			payload_data += 4 * getCC();
			payload_len -= 4 * getCC();
		}
		if(getExtension()) {
			/*
			* If set, the fixed header is followed by exactly one header extension.
			*/
			extension_hdr_t *rtpext;
			if (payload_len < 4)
				payload_len = 0;

			// the extension, if present, is after the CSRC list.
			rtpext = (extension_hdr_t *)((u_int8_t *)payload_data);
			payload_data += sizeof(extension_hdr_t) + rtpext->length;
			payload_len -= sizeof(extension_hdr_t) + rtpext->length;
		}
		frame->data = payload_data;
		frame->datalen = frame->datalen2 = payload_len > 0 ? payload_len : 0; /* ensure that datalen is never negative */

		if(codec == PAYLOAD_G723) {
			// voipmonitor does not handle SID packets well (silence packets) it causes out of sync
			if((unsigned char)payload_data[0] & 2)  {
				/* check if jitterbuffer is already created. If not we have to create it because 
				   if call starts with SID packets first it will than cause out of sync calls 
				*/
				if(ast_test_flag(&channel->jb, (1 << 2))) {
					// jitterbuffer is created so we can skip SID packets now
					return;
				}
			}
		}

		if(codec == PAYLOAD_G729 and (payload_len <= 12)) {
			frame->frametype = AST_FRAME_DTMF;
		}
	} else {
		frame->datalen2 = 0;
	}

	if(savePayload) {
		channel->rawstream = gfileRAW;
		Call *owner = (Call*)call_owner;
		if(iscaller) {
			owner->codec_caller = codec;
			if(owner->audiobuffer1) {
				channel->audiobuf = owner->audiobuffer1;
			}
		} else {
			owner->codec_called = codec;
			if(owner->audiobuffer2) {
				channel->audiobuf = owner->audiobuffer2;
			}
		}
		if(payload_len > 0) {
			channel->last_datalen = frame->datalen;
		}
	} else {
		frame->datalen = 0;
		frame->data = NULL;
		channel->rawstream = NULL;
	}

	// create jitter buffer structures 
	ast_jb_do_usecheck(channel, &header->ts);
	
	if(!channel->jb_reseted) {
		// initializing jitterbuffer 
		if(savePayload) {
			channel_record->jitter_max = frame->len * 3; 
		}
		
		ast_jb_empty_and_reset(channel);
		channel->jb_reseted = 1;
		memcpy(&channel->last_ts, &header->ts, sizeof(struct timeval));
		ast_jb_put(channel, frame, &header->ts);
		return;
	}

	/* calculate time difference between last packet and current packet + packetization time*/ 
	int msdiff = ast_tvdiff_ms( header->ts, ast_tvadd(channel->last_ts, ast_samp2tv(packetization, 1000)) );
	//printf("ms:%d\n", msdiff);
	if(msdiff > packetization * 1000) {
		// difference is too big, reseting last_ts to current packet. If we dont check this it could happen to run while cycle endlessly
		memcpy(&channel->last_ts, &header->ts, sizeof(struct timeval));
		ast_jb_put(channel, frame, &header->ts);
		if(verbosity > 4) syslog(LOG_ERR, "big timestamp jump (msdiff:%d packetization: %d) in this file: %s\n", msdiff, packetization, gfilename);
		return;
	}

	/* between last packet and current packet is big timestamp difference and it could count 
	 * interpolated framed although it was silence so calculate real number of packets based 
	 * on timestamps in packet header, timestamps in rtp header and sequence numbers between 
	 * last packet and current packet
	 */

	// relative time difference calculated from packet sequence 
	u_int32_t sequencems = (frame->seqno - last_seq) * packetization;

	/* difference (in ms) between timestamps in packet header and rtp timestamps. this should 
	 * be ideally equel to zero. Negative values mean that packet arrives earlier and positive 
	 * values indicates that packet was late 
	 */
	long double transit = (timeval_subtract(&tsdiff, header->ts, s->lastTimeRecJ) ? -timeval2micro(tsdiff)/1000.0 : timeval2micro(tsdiff)/1000.0) - (double)(getTimestamp() - s->lastTimeStampJ)/(double)samplerate/1000;
	
	/* and now if there is bigger (lets say one second) timestamp difference (calculated from packet headers) 
	 * between two last packets and transit time is equel or smaller than sequencems (with 200ms toleration), 
	 * it was silence and manually mark the frame which indicates to not count interpolated frame and resynchronize jitterbuffer
	 */
	if( msdiff > 1000 and (transit <= (sequencems + 200)) ) {
		if(verbosity > 4) printf("jitterbuffer: manually marking packet, msdiff(%d) > 1000 and transit (%Lf) <= ((sequencems(%u) + 200)\n", msdiff, transit, sequencems);
		frame->marker = 1;
	}
	
	// fetch packet from jitterbuffer every 20 ms regardless on packet loss or delay
	while( msdiff >= packetization )  {
		if(frame->marker or lastframetype == AST_FRAME_DTMF) {
			/* if last frame was marked or DTMF, ignore interpolated frames */
			channel->last_loss_burst = 0;
		}
		ast_jb_get_and_deliver(channel, &channel->last_ts);
		/* adding packetization time to last_ts time */ 
		struct timeval tmp = ast_tvadd(channel->last_ts, ast_samp2tv(frame->len, 1000));
		memcpy(&channel->last_ts, &tmp, sizeof(struct timeval));
		msdiff -= packetization;
	}

	//printf("s[%u] codec[%d]\n",getSeqNum(), codec);
	ast_jb_put(channel, frame, &header->ts);
}