diff -Naur parole-010beta2/audio.c parole-010beta3/audio.c --- parole-010beta2/audio.c 2013-02-19 11:55:50.512000921 +0100 +++ parole-010beta3/audio.c 2013-02-25 18:12:12.861751223 +0100 @@ -39,7 +39,7 @@ ad->hw_params = NULL; ad->rate = rate; ad->channels = channels; -/* ad->periods = */ + ad->periods = 10; /* ad->period_size = */ ad->period_time = 20000; /* ad->buffer_size = */ @@ -93,10 +93,10 @@ fprintf(stderr, MSGPREFIX"Cannot set period time (%s)\n", snd_strerror(err)); return -1; } -/* if ((err = snd_pcm_hw_params_set_periods(ad->pcm_handle, ad->hw_params, ad->periods, 0)) < 0) { + if ((err = snd_pcm_hw_params_set_periods(ad->pcm_handle, ad->hw_params, ad->periods, 0)) < 0) { fprintf(stderr, MSGPREFIX"Cannot set periods (%s)\n", snd_strerror(err)); return -1; - }*/ + } /* apply hardware parameters to pcm device and prepare device */ if (ad->verbose) fprintf(stderr, MSGPREFIX"Applying hardware parameters...\n"); @@ -198,7 +198,7 @@ /* playback: if the samples in ring buffer are >= start_threshold, and the stream is not running, it will be started capture: if we try to read a number of frames >= start_threshold, then the stream will be started */ - ad->start_threshold = 4*ad->period_size; + ad->start_threshold = 2*ad->period_size; if ((err = snd_pcm_sw_params_set_start_threshold(ad->pcm_handle, ad->sw_params, ad->start_threshold)) < 0) { fprintf(stderr, MSGPREFIX"Cannot set start threshold (%s)\n", snd_strerror(err)); return -1; diff -Naur parole-010beta2/Changelog parole-010beta3/Changelog --- parole-010beta2/Changelog 2013-02-19 12:30:28.002544922 +0100 +++ parole-010beta3/Changelog 2013-02-25 19:09:52.360818805 +0100 @@ -1,3 +1,11 @@ +version 0.10beta3: + + * Added variable to count overruns + * Added addr field to struct udp_packet_st and updated code + * Changed start_threshold for playback to 40ms + * Request 10 periods (200ms ringbuffers) to alsa driver + * Minor cosmetic changes + version 0.10beta2: * Cleanup: removed variables peak_count and t_poll diff -Naur parole-010beta2/parole.c parole-010beta3/parole.c --- parole-010beta2/parole.c 2013-02-19 12:39:06.005208829 +0100 +++ parole-010beta3/parole.c 2013-02-25 18:56:54.857769152 +0100 @@ -41,7 +41,7 @@ #include "oggopus.h" #include "notes.h" -#define VERSION "0.10beta2" +#define VERSION "0.10beta3" #define DEBUGOGG 0 #define UDP_PACKET_CLR_HEADER_LEN 4 @@ -74,8 +74,9 @@ * This means that n>0 always and (opus_packetlen + n) % 8 = 0 */ struct udp_packet_st { - uint8_t data[UDP_PACKET_MAXLEN]; - size_t len; + struct sockaddr_in addr; + uint8_t data[UDP_PACKET_MAXLEN]; + size_t len; }; static volatile sig_atomic_t keep_going; @@ -221,12 +222,12 @@ return 0; } -void send_udp_packet(int sockfd, struct sockaddr_in *address, struct udp_packet_st *udp_packet) +void send_udp_packet(int sockfd, struct udp_packet_st *udp_packet) { ssize_t nw; nw = sendto(sockfd, udp_packet->data, udp_packet->len, 0, - (struct sockaddr *)address, sizeof(*address)); + (struct sockaddr *)&udp_packet->addr, sizeof(udp_packet->addr)); if (nw == -1) { perror("sendto()"); exit(1); @@ -235,15 +236,15 @@ fprintf(stderr, "sendto() returned %zd, expected %zd\n", nw, udp_packet->len); } -void receive_udp_packet(int sockfd, struct sockaddr_in *address, struct udp_packet_st *udp_packet) +void receive_udp_packet(int sockfd, struct udp_packet_st *udp_packet) { ssize_t nr; - socklen_t address_len; + socklen_t addr_len; udp_packet->len = UDP_PACKET_MAXLEN; - address_len = sizeof(*address); + addr_len = sizeof(udp_packet->addr); nr = recvfrom(sockfd, udp_packet->data, udp_packet->len, 0, - (struct sockaddr *)address, &address_len); + (struct sockaddr *)&udp_packet->addr, &addr_len); if (nr == -1) { perror("recvfrom()"); exit(1); @@ -482,7 +483,6 @@ /* udp socket */ int sockfd; - struct sockaddr_in src_addr; int local_port = 8110; struct sockaddr_in local_addr; char *remote_host = NULL; @@ -499,7 +499,7 @@ char *audiodevice = "hw:0,0"; const unsigned int rate = 48000, channels = 2; float peak_percent; - int keep_going_capture, underruns; + int keep_going_capture, overruns, underruns; /* opus encoder */ OpusEncoder *enc; @@ -620,7 +620,7 @@ /* read key if the user requested encryption */ if (encrypt) { ret = read_key(key, keyfile); - if (ret != 0) + if (ret == -1) die("Error: cannot read key.\n"); if (verbose) print_key(key); @@ -646,13 +646,14 @@ iv[0] = iv[1] = 0; xtea_encrypt_buffer_cbc(udp_packet.data + 8, udp_packet.len - 8, key, iv); } - send_udp_packet(sockfd, &remote_addr, &udp_packet); + udp_packet.addr = remote_addr; + send_udp_packet(sockfd, &udp_packet); /* receive packet from remote host */ fprintf(stderr, "Call request sent, waiting for reply...\n"); do { - receive_udp_packet(sockfd, &src_addr, &udp_packet); - } while (!is_same_addr(src_addr, remote_addr)); + receive_udp_packet(sockfd, &udp_packet); + } while (!is_same_addr(udp_packet.addr, remote_addr)); /* check if the other side accepted the call */ if (udp_packet.len == 2 && strncmp((char *)udp_packet.data, "OK", 2) == 0) @@ -678,7 +679,8 @@ /* listen for a call request (this call will block) */ fprintf(stderr, "Listening for incoming calls on udp port %d...\n", local_port); - receive_udp_packet(sockfd, &remote_addr, &udp_packet); + receive_udp_packet(sockfd, &udp_packet); + remote_addr = udp_packet.addr; /* is it a valid CALL packet? */ if (udp_packet.len == 8 && strncmp((char *)udp_packet.data, "CALL-CLR", 8) == 0) { @@ -723,7 +725,7 @@ uint32_t a0, a1, b0, b1; ret = read_key(key, keyfile); - if (ret != 0) + if (ret == -1) die("Error: cannot read key.\n"); if (verbose) print_key(key); @@ -746,7 +748,8 @@ /* send response */ udp_packet.len = 2; memcpy(udp_packet.data, answer == 'y' ? "OK" : "NO", udp_packet.len); - send_udp_packet(sockfd, &remote_addr, &udp_packet); + udp_packet.addr = remote_addr; + send_udp_packet(sockfd, &udp_packet); if (answer == 'y') break; @@ -853,6 +856,7 @@ total_bytes_out = 0; total_bytes_in = 0; peak_percent = 0.0f; + overruns = 0; underruns = 0; packets_lost = 0; @@ -886,11 +890,11 @@ if (pfds[0].revents & POLLIN) { gettimeofday(&tda0, NULL); /* read udp_packet */ - receive_udp_packet(sockfd, &src_addr, &udp_packet); + receive_udp_packet(sockfd, &udp_packet); total_bytes_in += udp_packet.len; /* make sure this packet comes from the remote host */ - if (is_same_addr(src_addr, remote_addr)) { + if (is_same_addr(udp_packet.addr, remote_addr)) { /* read packet header and reset timeout counter */ sequence_number = read_be32(udp_packet.data); timeout = 0; @@ -971,8 +975,8 @@ //fprintf(stderr, "Oops, packet duplicated or out of order.\n"); } } else { - fprintf(stderr, "unexpected packet from: %s:%hu\n", - inet_ntoa(src_addr.sin_addr), ntohs(src_addr.sin_port)); + fprintf(stderr, "Unexpected packet from: %s:%hu\n", + inet_ntoa(udp_packet.addr.sin_addr), ntohs(udp_packet.addr.sin_port)); } gettimeofday(&tda1, NULL); @@ -996,6 +1000,7 @@ ret = audio_read(&ad_capture, 1); if (ret < 0) { /* overrun, let's handle it and try again */ + overruns++; ret = audio_recover(&ad_capture, ret, 1); if (ret == 0) { ret = audio_start(&ad_capture); @@ -1020,7 +1025,7 @@ timeout++; if (timeout == 250) { keep_going = 0; - fprintf(stderr, "timeout\n"); + fprintf(stderr, "Timeout\n"); } /* find peak in captured audio */ @@ -1072,7 +1077,8 @@ total_bytes_out += udp_packet.len; /* send udp packet */ - send_udp_packet(sockfd, &remote_addr, &udp_packet); + udp_packet.addr = remote_addr; + send_udp_packet(sockfd, &udp_packet); if (record) { /* forge ogg packet */ @@ -1132,7 +1138,7 @@ /* check if we still have stuff on the socket */ while ((pollret = poll(pfds, 1, 250)) > 0) { if (pfds[0].revents & POLLIN) - receive_udp_packet(sockfd, &src_addr, &udp_packet); + receive_udp_packet(sockfd, &udp_packet); } /* reset signal handler */ diff -Naur parole-010beta2/README parole-010beta3/README --- parole-010beta2/README 2013-02-19 11:52:23.512000856 +0100 +++ parole-010beta3/README 2013-02-25 19:56:27.360415996 +0100 @@ -104,7 +104,7 @@ parole uses alsa for audio capture and playback. You can specify the alsa device to use with -d option. If you get and error with the default device (hw:0,0), -try 'plughw:0,0'. +try 'plughw:0,0'. It should be possible to use pulseaudio with -d pulse. Note that internally parole uses the following format: 2 channels, 48000Hz sampling rate, s16_le format. So if your sound card does not support this format you're likely to get an error when alsa is initialized. @@ -120,7 +120,7 @@ parole supports basic encryption with a symmetric key (that is, people wanting to make an encrypted call must decide a common key before starting the call). This key is 128-bit long, and can be represented by a 32-char hexadecimal -number. To encrypt a call both ends must use the -e option, in which case the +number. To encrypt a call the caller must use the -e option, in which case the program will ask both parts to enter the key and will start the communication only if the keys match. If the key you enter is composed of less than 32 characters, it will be padded with '0's. The key can also be read from a file, diff -Naur parole-010beta2/TODO parole-010beta3/TODO --- parole-010beta2/TODO 2013-02-19 12:46:47.002621493 +0100 +++ parole-010beta3/TODO 2013-02-25 19:03:55.362550478 +0100 @@ -1,3 +0,0 @@ -* Make it work with pulseaudio (it might already work with newest versions) -* Add code to minimize audio delay, which increases when alsa playback - ringbuffer fills