static APR_INLINE apt_bool_t mpf_rtp_data_send(mpf_rtp_stream_t *rtp_stream, rtp_transmitter_t *transmitter, const mpf_frame_t *frame) { apt_bool_t status = TRUE; memcpy( transmitter->packet_data + transmitter->packet_size, frame->codec_frame.buffer, frame->codec_frame.size); transmitter->packet_size += frame->codec_frame.size; if(++transmitter->current_frames == transmitter->packet_frames) { rtp_header_t *header = (rtp_header_t*)transmitter->packet_data; header->sequence = htons(++transmitter->last_seq_num); RTP_TRACE("> RTP time=%6u ssrc=%8x pt=%3u %cts=%9u seq=%5hu\n", (apr_uint32_t)apr_time_usec(apr_time_now()), transmitter->sr_stat.ssrc, header->type, (header->marker == 1) ? '*' : ' ', header->timestamp, transmitter->last_seq_num); header->timestamp = htonl(header->timestamp); if(apr_socket_sendto( rtp_stream->rtp_socket, rtp_stream->rtp_r_sockaddr, 0, transmitter->packet_data, &transmitter->packet_size) == APR_SUCCESS) { transmitter->sr_stat.sent_packets++; transmitter->sr_stat.sent_octets += (apr_uint32_t)transmitter->packet_size - sizeof(rtp_header_t); } else { status = FALSE; } transmitter->current_frames = 0; } return status; }
static APR_INLINE rtp_ts_result_e rtp_rx_ts_update(rtp_receiver_t *receiver, mpf_codec_descriptor_t *descriptor, apr_time_t *time, apr_uint32_t ts) { apr_int32_t deviation; /* arrival time diff in samples */ deviation = (apr_int32_t)apr_time_as_msec(*time - receiver->history.time_last) * descriptor->channel_count * descriptor->sampling_rate / 1000; /* arrival timestamp diff */ deviation -= ts - receiver->history.ts_last; if(deviation < 0) { deviation = -deviation; } if(deviation > DEVIATION_THRESHOLD) { return RTP_TS_DRIFT; } receiver->rr_stat.jitter += deviation - ((receiver->rr_stat.jitter + 8) >> 4); RTP_TRACE("jitter=%d deviation=%d\n",receiver->rr_stat.jitter,deviation); receiver->history.time_last = *time; receiver->history.ts_last = ts; if(receiver->rr_stat.jitter < receiver->periodic_history.jitter_min) { receiver->periodic_history.jitter_min = receiver->rr_stat.jitter; } if(receiver->rr_stat.jitter > receiver->periodic_history.jitter_max) { receiver->periodic_history.jitter_max = receiver->rr_stat.jitter; } return RTP_TS_UPDATE; }
static APR_INLINE rtp_ts_result_e rtp_rx_ts_update(rtp_receiver_t *receiver, mpf_codec_descriptor_t *descriptor, apr_time_t *time, apr_uint32_t ts, apr_byte_t *marker) { apr_int32_t deviation; apr_int32_t time_diff; /* arrival time diff in msec */ time_diff = (apr_int32_t)apr_time_as_msec(*time - receiver->history.time_last); /* if the time difference is more than the threshold (INTER_TALKSPURT_GAP), and the marker is not set, then this might be a beginning of a new malformed talkspurt */ if(!*marker && time_diff > INTER_TALKSPURT_GAP) { /* set the missing marker */ *marker = 1; } /* arrival time diff in samples */ deviation = time_diff * descriptor->channel_count * descriptor->sampling_rate / 1000; /* arrival timestamp diff */ deviation -= ts - receiver->history.ts_last; if(deviation < 0) { deviation = -deviation; } if(deviation > DEVIATION_THRESHOLD) { return RTP_TS_DRIFT; } receiver->rr_stat.jitter += deviation - ((receiver->rr_stat.jitter + 8) >> 4); RTP_TRACE("jitter=%u deviation=%d\n",receiver->rr_stat.jitter,deviation); receiver->history.time_last = *time; receiver->history.ts_last = ts; if(receiver->rr_stat.jitter < receiver->periodic_history.jitter_min) { receiver->periodic_history.jitter_min = receiver->rr_stat.jitter; } if(receiver->rr_stat.jitter > receiver->periodic_history.jitter_max) { receiver->periodic_history.jitter_max = receiver->rr_stat.jitter; } return RTP_TS_UPDATE; }
static APR_INLINE apt_bool_t mpf_rtp_event_send(mpf_rtp_stream_t *rtp_stream, rtp_transmitter_t *transmitter, const mpf_frame_t *frame) { char packet_data[20]; apr_size_t packet_size = sizeof(rtp_header_t) + sizeof(mpf_named_event_frame_t); rtp_header_t *header = (rtp_header_t*) packet_data; mpf_named_event_frame_t *named_event = (mpf_named_event_frame_t*)(header+1); rtp_header_prepare( transmitter, header, rtp_stream->base->tx_event_descriptor->payload_type, (frame->marker == MPF_MARKER_START_OF_EVENT) ? 1 : 0, transmitter->timestamp_base); *named_event = frame->event_frame; named_event->edge = (frame->marker == MPF_MARKER_END_OF_EVENT) ? 1 : 0; header->sequence = htons(++transmitter->last_seq_num); RTP_TRACE("> RTP time=%6lu ssrc=%8lx pt=%3u %cts=%9lu seq=%5u event=%2u dur=%3u %c\n", (apr_uint32_t)apr_time_usec(apr_time_now()), transmitter->sr_stat.ssrc, header->type, (header->marker == 1) ? '*' : ' ', header->timestamp, transmitter->last_seq_num, named_event->event_id, named_event->duration, (named_event->edge == 1) ? '*' : ' '); header->timestamp = htonl(header->timestamp); named_event->duration = htons((apr_uint16_t)named_event->duration); if(apr_socket_sendto( rtp_stream->rtp_socket, rtp_stream->rtp_r_sockaddr, 0, packet_data, &packet_size) != APR_SUCCESS) { return FALSE; } transmitter->sr_stat.sent_packets++; transmitter->sr_stat.sent_octets += sizeof(mpf_named_event_frame_t); return TRUE; }
static apt_bool_t rtp_rx_packet_receive(mpf_rtp_stream_t *rtp_stream, void *buffer, apr_size_t size) { rtp_receiver_t *receiver = &rtp_stream->receiver; mpf_codec_descriptor_t *descriptor = rtp_stream->base->rx_descriptor; apr_time_t time; rtp_ssrc_result_e ssrc_result; rtp_header_t *header = rtp_rx_header_skip(&buffer,&size); if(!header) { /* invalid RTP packet */ receiver->stat.invalid_packets++; return FALSE; } header->sequence = ntohs((apr_uint16_t)header->sequence); header->timestamp = ntohl(header->timestamp); header->ssrc = ntohl(header->ssrc); time = apr_time_now(); RTP_TRACE("RTP time=%6u ssrc=%8x pt=%3u %cts=%9u seq=%5u size=%"APR_SIZE_T_FMT"\n", (apr_uint32_t)apr_time_usec(time), header->ssrc, header->type, (header->marker == 1) ? '*' : ' ', header->timestamp, header->sequence, size); if(!receiver->stat.received_packets) { /* initialization */ rtp_rx_stat_init(receiver,header,&time); } ssrc_result = rtp_rx_ssrc_update(receiver,header->ssrc); if(ssrc_result == RTP_SSRC_PROBATION) { receiver->stat.invalid_packets++; return FALSE; } else if(ssrc_result == RTP_SSRC_RESTART) { rtp_rx_restart(receiver); rtp_rx_stat_init(receiver,header,&time); } rtp_rx_seq_update(receiver,(apr_uint16_t)header->sequence); if(header->type == descriptor->payload_type) { /* codec */ apr_byte_t marker = (apr_byte_t)header->marker; if(rtp_rx_ts_update(receiver,descriptor,&time,header->timestamp,&marker) == RTP_TS_DRIFT) { rtp_rx_restart(receiver); return FALSE; } if(mpf_jitter_buffer_write(receiver->jb,buffer,size,header->timestamp,marker) != JB_OK) { receiver->stat.discarded_packets++; rtp_rx_failure_threshold_check(receiver); } } else if(rtp_stream->base->rx_event_descriptor && header->type == rtp_stream->base->rx_event_descriptor->payload_type) { /* named event */ mpf_named_event_frame_t *named_event = (mpf_named_event_frame_t *)buffer; named_event->duration = ntohs((apr_uint16_t)named_event->duration); if(mpf_jitter_buffer_event_write(receiver->jb,named_event,header->timestamp,(apr_byte_t)header->marker) != JB_OK) { receiver->stat.discarded_packets++; } } else if(header->type == RTP_PT_CN) { /* CN packet */ receiver->stat.ignored_packets++; } else { /* invalid payload type */ receiver->stat.ignored_packets++; } return TRUE; }