git-svn-id: svn+ssh://jackaudio.org/trunk/jack@3127 0c269be4-1314-0410-8aa9-9f06e86f4224tags/0.115.6
| @@ -85,29 +85,116 @@ net_driver_wait (net_driver_t *driver, int extra_fd, int *status, float *delayed | |||
| // on packet loss we should either detect an xrun or just continue running when we | |||
| // think, that the sync source is not running anymore. | |||
| socklen_t address_size = sizeof (struct sockaddr_in); | |||
| int bufsize, len; | |||
| //socklen_t address_size = sizeof (struct sockaddr_in); | |||
| //int len; | |||
| int we_have_the_expected_frame = 0; | |||
| jack_nframes_t next_frame_avail; | |||
| jacknet_packet_header *pkthdr = (jacknet_packet_header *) driver->rx_buf; | |||
| bufsize = get_sample_size (driver->bitdepth) * driver->capture_channels * driver->net_period_down + sizeof (jacknet_packet_header); | |||
| if( !driver->next_deadline_valid ) { | |||
| driver->next_deadline = jack_get_microseconds() + 2*driver->period_usecs; | |||
| driver->next_deadline_valid = 1; | |||
| } else { | |||
| driver->next_deadline += driver->period_usecs; | |||
| } | |||
| if (netjack_poll (driver->sockfd, 500)) | |||
| len = netjack_recvfrom (driver->sockfd, (char *)driver->rx_buf, bufsize, MSG_WAITALL, (struct sockaddr*) & driver->syncsource_address, &address_size, driver->mtu); | |||
| else | |||
| len = 0; | |||
| while (len != bufsize) | |||
| { | |||
| jack_error ("wrong_packet_len: len=%d, expected=%d", len, bufsize); | |||
| if (netjack_poll (driver->sockfd, 500)) | |||
| len = netjack_recvfrom (driver->sockfd, (char *)driver->rx_buf, bufsize, MSG_WAITALL, (struct sockaddr*) & driver->syncsource_address, &address_size, driver->mtu); | |||
| else | |||
| len = 0; | |||
| while(1) { | |||
| if( ! netjack_poll_deadline( driver->sockfd, driver->next_deadline ) ) | |||
| break; | |||
| packet_cache_drain_socket( global_packcache, driver->sockfd ); | |||
| if( packet_cache_get_next_available_framecnt( global_packcache, driver->expected_framecnt, &next_frame_avail) ) { | |||
| if( next_frame_avail == driver->expected_framecnt ) { | |||
| we_have_the_expected_frame = 1; | |||
| break; | |||
| } | |||
| //printf( "next frame = %d (exp: %d) \n", next_frame_avail, driver->expected_framecnt ); | |||
| } | |||
| } | |||
| driver->running_free = 0; | |||
| if( we_have_the_expected_frame ) { | |||
| packet_cache_retreive_packet( global_packcache, driver->expected_framecnt, (char *) driver->rx_buf, driver->rx_bufsize ); | |||
| driver->packet_data_valid = 1; | |||
| //printf( "ok... %d\n", driver->expected_framecnt ); | |||
| } else { | |||
| // bah... the packet is not there. | |||
| // either | |||
| // - it got lost. | |||
| // - its late | |||
| // - sync source is not sending anymore. | |||
| // lets check if we have the next packets, we will just run a cycle without data. | |||
| // in that case. | |||
| if( packet_cache_get_next_available_framecnt( global_packcache, driver->expected_framecnt, &next_frame_avail) ) | |||
| { | |||
| jack_nframes_t offset = next_frame_avail - driver->expected_framecnt; | |||
| if( offset < driver->resync_threshold ) { | |||
| // ok. dont do nothing. we will run without data. | |||
| // this seems to be one or 2 lost packets. | |||
| driver->packet_data_valid = 0; | |||
| //printf( "lost packet... %d\n", driver->expected_framecnt ); | |||
| } else { | |||
| // the diff is too high. but we have a packet. | |||
| // lets resync. | |||
| driver->expected_framecnt = next_frame_avail; | |||
| packet_cache_retreive_packet( global_packcache, driver->expected_framecnt, (char *) driver->rx_buf, driver->rx_bufsize ); | |||
| driver->next_deadline_valid = 0; | |||
| driver->packet_data_valid = 1; | |||
| //printf( "resync... expected: %d, offset=%d\n", driver->expected_framecnt, offset ); | |||
| } | |||
| } else { | |||
| // no packets in buffer. | |||
| driver->packet_data_valid = 0; | |||
| if( driver->num_lost_packets < 3 ) { | |||
| // increase deadline. | |||
| driver->next_deadline += driver->period_usecs/4; | |||
| // might be lost packets. | |||
| // continue | |||
| } else if( (driver->num_lost_packets <= 10) ) { | |||
| // lets try adjusting the deadline, for some packets, we might have just ran 2 fast. | |||
| } else { | |||
| // give up. lets run freely. | |||
| driver->running_free = 1; | |||
| // But now we can check for any new frame available. | |||
| if( packet_cache_get_next_available_framecnt( global_packcache, 0, &next_frame_avail) ) { | |||
| driver->expected_framecnt = next_frame_avail; | |||
| packet_cache_retreive_packet( global_packcache, driver->expected_framecnt, (char *) driver->rx_buf, driver->rx_bufsize ); | |||
| driver->next_deadline_valid = 0; | |||
| driver->packet_data_valid = 1; | |||
| driver->running_free = 1; | |||
| //printf( "resync after freerun... %d\n", driver->expected_framecnt ); | |||
| } | |||
| } | |||
| //printf( "free... %d\n", driver->expected_framecnt ); | |||
| } | |||
| } | |||
| packet_header_ntoh (pkthdr); | |||
| if( !driver->packet_data_valid ) | |||
| driver->num_lost_packets += 1; | |||
| else { | |||
| driver->num_lost_packets = 0; | |||
| packet_header_ntoh (pkthdr); | |||
| } | |||
| framecnt = driver->expected_framecnt; | |||
| driver->expected_framecnt += 1; | |||
| driver->last_wait_ust = jack_get_microseconds (); | |||
| driver->engine->transport_cycle_start (driver->engine, driver->last_wait_ust); | |||
| /* this driver doesn't work so well if we report a delay */ | |||
| /* XXX: this might not be the case anymore */ | |||
| *delayed_usecs = 0; /* lie about it */ | |||
| *status = 0; | |||
| return driver->period_size; | |||
| @@ -123,19 +210,9 @@ net_driver_run_cycle (net_driver_t *driver) | |||
| jack_nframes_t nframes = net_driver_wait (driver, -1, &wait_status, | |||
| &delayed_usecs); | |||
| // currently there is no xrun detection. | |||
| // so nframes will always be period_size. | |||
| // XXX: i uncomment this code because the signature of delay() | |||
| // changed samewhere in the 0.99.x series. so this is the showstopper for 0.99.0 | |||
| #if 0 | |||
| if (nframes == 0) { | |||
| /* we detected an xrun and restarted: notify | |||
| * clients about the delay. */ | |||
| engine->delay (engine, delayed_usecs); | |||
| return 0; | |||
| } | |||
| #endif | |||
| // XXX: xrun code removed. | |||
| // especially with celt there are no real xruns anymore. | |||
| // things are different on the net. | |||
| if (wait_status == 0) | |||
| return engine->run_cycle (engine, nframes, delayed_usecs); | |||
| @@ -149,6 +226,10 @@ net_driver_run_cycle (net_driver_t *driver) | |||
| static int | |||
| net_driver_null_cycle (net_driver_t* driver, jack_nframes_t nframes) | |||
| { | |||
| // TODO: talk to paul about this. | |||
| // do i wait here ? | |||
| // just sending out a packet marked with junk ? | |||
| //int rx_size = get_sample_size(driver->bitdepth) * driver->capture_channels * driver->net_period_down + sizeof(jacknet_packet_header); | |||
| int tx_size = get_sample_size(driver->bitdepth) * driver->playback_channels * driver->net_period_up + sizeof(jacknet_packet_header); | |||
| unsigned int *packet_buf, *packet_bufX; | |||
| @@ -157,7 +238,7 @@ net_driver_null_cycle (net_driver_t* driver, jack_nframes_t nframes) | |||
| jacknet_packet_header *tx_pkthdr = (jacknet_packet_header *)packet_buf; | |||
| jacknet_packet_header *rx_pkthdr = (jacknet_packet_header *)driver->rx_buf; | |||
| framecnt = rx_pkthdr->framecnt; | |||
| //framecnt = rx_pkthdr->framecnt; | |||
| driver->reply_port = rx_pkthdr->reply_port; | |||
| @@ -195,14 +276,15 @@ net_driver_bufsize (net_driver_t* driver, jack_nframes_t nframes) | |||
| static int | |||
| net_driver_read (net_driver_t* driver, jack_nframes_t nframes) | |||
| { | |||
| //jack_default_audio_sample_t* buf; | |||
| //jack_port_t *port; | |||
| jack_position_t local_trans_pos; | |||
| jack_transport_state_t local_trans_state; | |||
| //int bufsize = get_sample_size(driver->bitdepth) * driver->capture_channels * driver->net_period_down + sizeof(jacknet_packet_header); | |||
| unsigned int *packet_buf, *packet_bufX; | |||
| if( ! driver->packet_data_valid ) { | |||
| render_payload_to_jack_ports (driver->bitdepth, NULL, driver->net_period_down, driver->capture_ports, driver->capture_srcs, nframes); | |||
| return 0; | |||
| } | |||
| packet_buf = driver->rx_buf; | |||
| jacknet_packet_header *pkthdr = (jacknet_packet_header *)packet_buf; | |||
| @@ -217,6 +299,8 @@ net_driver_read (net_driver_t* driver, jack_nframes_t nframes) | |||
| framecnt = pkthdr->framecnt; | |||
| driver->reply_port = pkthdr->reply_port; | |||
| driver->latency = pkthdr->latency; | |||
| driver->resync_threshold = pkthdr->latency-1; | |||
| // check whether, we should handle the transport sync stuff, or leave trnasports untouched. | |||
| if (driver->handle_transport_sync) { | |||
| @@ -277,10 +361,13 @@ net_driver_write (net_driver_t* driver, jack_nframes_t nframes) | |||
| uint32_t *packet_buf, *packet_bufX; | |||
| int packet_size = get_sample_size(driver->bitdepth) * driver->playback_channels * driver->net_period_up + sizeof(jacknet_packet_header); | |||
| jacknet_packet_header *pkthdr; | |||
| packet_buf = alloca(packet_size); | |||
| pkthdr = (jacknet_packet_header *)packet_buf; | |||
| jacknet_packet_header *pkthdr = (jacknet_packet_header *)packet_buf; | |||
| if( driver->running_free ) | |||
| return 0; | |||
| // offset packet_bufX by the packetheader. | |||
| packet_bufX = packet_buf + sizeof(jacknet_packet_header) / sizeof(jack_default_audio_sample_t); | |||
| @@ -294,6 +381,7 @@ net_driver_write (net_driver_t* driver, jack_nframes_t nframes) | |||
| if (driver->srcaddress_valid) | |||
| if (driver->reply_port) | |||
| driver->syncsource_address.sin_port = htons(driver->reply_port); | |||
| netjack_sendto(driver->outsockfd, (char *)packet_buf, packet_size, | |||
| 0, (struct sockaddr*)&driver->syncsource_address, sizeof(struct sockaddr_in), driver->mtu); | |||
| @@ -454,7 +542,7 @@ net_driver_new (jack_client_t * client, | |||
| unsigned int bitdepth) | |||
| { | |||
| net_driver_t * driver; | |||
| int first_pack_len, rx_bufsize; | |||
| int first_pack_len; | |||
| struct sockaddr_in address; | |||
| jack_info ("creating net driver ... %s|%" PRIu32 "|%" PRIu32 | |||
| @@ -537,6 +625,8 @@ net_driver_new (jack_client_t * client, | |||
| jack_info ("Waiting for an incoming packet !!!"); | |||
| jack_info ("*** IMPORTANT *** Dont connect a client to jackd until the driver is attached to a clock source !!!"); | |||
| // XXX: netjack_poll polls forever. | |||
| // thats ok here. | |||
| if (netjack_poll (driver->sockfd, 500)) | |||
| first_pack_len = recvfrom (driver->sockfd, first_packet, sizeof (jacknet_packet_header), 0, (struct sockaddr*) & driver->syncsource_address, &address_size); | |||
| else | |||
| @@ -592,7 +682,7 @@ net_driver_new (jack_client_t * client, | |||
| // After possible Autoconfig: do all calculations... | |||
| driver->period_usecs = | |||
| (jack_time_t) floor ((((float) driver->period_size) / driver->sample_rate) | |||
| (jack_time_t) floor ((((float) driver->period_size) / (float)driver->sample_rate) | |||
| * 1000000.0f); | |||
| if( driver->bitdepth == 1000 ) { | |||
| @@ -605,17 +695,23 @@ net_driver_new (jack_client_t * client, | |||
| driver->net_period_up = (float) driver->period_size / (float) resample_factor_up; | |||
| } | |||
| /* TODO: this seems... useles */ | |||
| rx_bufsize = sizeof (jacknet_packet_header) + driver->net_period_down * driver->capture_channels * get_sample_size (driver->bitdepth); | |||
| driver->rx_buf = malloc (rx_bufsize); | |||
| driver->pkt_buf = malloc (rx_bufsize); | |||
| global_packcache = packet_cache_new (driver->latency + 5, rx_bufsize, driver->mtu); | |||
| driver->rx_bufsize = sizeof (jacknet_packet_header) + driver->net_period_down * driver->capture_channels * get_sample_size (driver->bitdepth); | |||
| driver->rx_buf = malloc (driver->rx_bufsize); | |||
| driver->pkt_buf = malloc (driver->rx_bufsize); | |||
| global_packcache = packet_cache_new (driver->latency + 5, driver->rx_bufsize, driver->mtu); | |||
| driver->expected_framecnt_valid = 0; | |||
| driver->num_lost_packets = 0; | |||
| driver->next_deadline_valid = 0; | |||
| driver->resync_threshold = driver->latency - 1; | |||
| driver->running_free = 0; | |||
| jack_info ("netjack: period : up: %d / dn: %d", driver->net_period_up, driver->net_period_down); | |||
| jack_info ("netjack: framerate: %d", driver->sample_rate); | |||
| jack_info ("netjack: audio : cap: %d / pbk: %d)", driver->capture_channels_audio, driver->playback_channels_audio); | |||
| jack_info ("netjack: midi : cap: %d / pbk: %d)", driver->capture_channels_midi, driver->playback_channels_midi); | |||
| jack_info ("netjack: buffsize : rx: %d)", rx_bufsize); | |||
| jack_info ("netjack: buffsize : rx: %d)", driver->rx_bufsize); | |||
| return (jack_driver_t *) driver; | |||
| } | |||
| @@ -72,8 +72,20 @@ struct _net_driver | |||
| unsigned int *rx_buf; | |||
| unsigned int *pkt_buf; | |||
| unsigned int rx_bufsize; | |||
| //unsigned int tx_bufsize; | |||
| unsigned int mtu; | |||
| unsigned int latency; | |||
| jack_nframes_t expected_framecnt; | |||
| int expected_framecnt_valid; | |||
| unsigned int num_lost_packets; | |||
| jack_time_t next_deadline; | |||
| int next_deadline_valid; | |||
| int packet_data_valid; | |||
| int resync_threshold; | |||
| int running_free; | |||
| }; | |||
| #endif /* __JACK_NET_DRIVER_H__ */ | |||
| @@ -41,7 +41,11 @@ | |||
| #include <sys/types.h> | |||
| #include <sys/socket.h> | |||
| #include <netinet/in.h> | |||
| // for ppoll | |||
| #define __USE_GNU | |||
| #include <poll.h> | |||
| #include <errno.h> | |||
| #include <signal.h> | |||
| @@ -115,7 +119,7 @@ packet_cache | |||
| int fragment_payload_size = mtu - sizeof (jacknet_packet_header); | |||
| int fragment_number = (pkt_size - sizeof (jacknet_packet_header) - 1) / fragment_payload_size + 1; | |||
| int i; | |||
| packet_cache *pcache = malloc (sizeof (packet_cache)); | |||
| if (pcache == NULL) | |||
| { | |||
| @@ -146,6 +150,7 @@ packet_cache | |||
| return NULL; | |||
| } | |||
| } | |||
| pcache->mtu = mtu; | |||
| return pcache; | |||
| } | |||
| @@ -197,10 +202,15 @@ cache_packet | |||
| return retval; | |||
| } | |||
| // TODO: fix wrapping case... need to pass | |||
| // current expected frame here. | |||
| // | |||
| // or just save framecount into packet_cache. | |||
| cache_packet | |||
| *packet_cache_get_oldest_packet (packet_cache *pcache) | |||
| { | |||
| jack_nframes_t minimal_frame = 0; | |||
| jack_nframes_t minimal_frame = JACK_MAX_FRAMES; | |||
| cache_packet *retval = &(pcache->packets[0]); | |||
| int i; | |||
| @@ -216,7 +226,6 @@ cache_packet | |||
| return retval; | |||
| } | |||
| cache_packet | |||
| *packet_cache_get_free_packet (packet_cache *pcache) | |||
| { | |||
| @@ -274,9 +283,10 @@ cache_packet_add_fragment (cache_packet *pack, char *packet_buf, int rcv_len) | |||
| return; | |||
| } | |||
| if (fragment_nr == 0) | |||
| { | |||
| memcpy (pack->packet_buf, packet_buf, pack->mtu); | |||
| memcpy (pack->packet_buf, packet_buf, rcv_len); | |||
| pack->fragment_array[0] = 1; | |||
| return; | |||
| @@ -305,6 +315,70 @@ cache_packet_is_complete (cache_packet *pack) | |||
| return TRUE; | |||
| } | |||
| // new poll using nanoseconds resolution and | |||
| // not waiting forever. | |||
| int | |||
| netjack_poll_deadline (int sockfd, jack_time_t deadline) | |||
| { | |||
| struct pollfd fds; | |||
| int i, poll_err = 0; | |||
| sigset_t sigmask; | |||
| struct sigaction action; | |||
| struct timespec timeout_spec = { 0, 0 }; | |||
| jack_time_t now = jack_get_microseconds(); | |||
| if( now >= deadline ) | |||
| return 0; | |||
| timeout_spec.tv_nsec = (deadline - now) * 1000; | |||
| sigemptyset(&sigmask); | |||
| sigaddset(&sigmask, SIGHUP); | |||
| sigaddset(&sigmask, SIGINT); | |||
| sigaddset(&sigmask, SIGQUIT); | |||
| sigaddset(&sigmask, SIGPIPE); | |||
| sigaddset(&sigmask, SIGTERM); | |||
| sigaddset(&sigmask, SIGUSR1); | |||
| sigaddset(&sigmask, SIGUSR2); | |||
| action.sa_handler = SIG_DFL; | |||
| action.sa_mask = sigmask; | |||
| action.sa_flags = SA_RESTART; | |||
| for (i = 1; i < NSIG; i++) | |||
| if (sigismember (&sigmask, i)) | |||
| sigaction (i, &action, 0); | |||
| fds.fd = sockfd; | |||
| fds.events = POLLIN; | |||
| poll_err = ppoll (&fds, 1, &timeout_spec, &sigmask); | |||
| if (poll_err == -1) | |||
| { | |||
| switch (errno) | |||
| { | |||
| case EBADF: | |||
| jack_error ("Error %d: An invalid file descriptor was given in one of the sets", errno); | |||
| break; | |||
| case EFAULT: | |||
| jack_error ("Error %d: The array given as argument was not contained in the calling program's address space", errno); | |||
| break; | |||
| case EINTR: | |||
| jack_error ("Error %d: A signal occurred before any requested event", errno); | |||
| break; | |||
| case EINVAL: | |||
| jack_error ("Error %d: The nfds value exceeds the RLIMIT_NOFILE value", errno); | |||
| break; | |||
| case ENOMEM: | |||
| jack_error ("Error %d: There was no space to allocate file descriptor tables", errno); | |||
| break; | |||
| } | |||
| } | |||
| return poll_err; | |||
| } | |||
| int | |||
| netjack_poll (int sockfd, int timeout) | |||
| { | |||
| @@ -365,6 +439,122 @@ netjack_poll (int sockfd, int timeout) | |||
| return TRUE; | |||
| } | |||
| // This now reads all a socket has into the cache. | |||
| // replacing netjack_recv functions. | |||
| void | |||
| packet_cache_drain_socket( packet_cache *pcache, int sockfd ) | |||
| { | |||
| char *rx_packet = alloca (pcache->mtu); | |||
| jacknet_packet_header *pkthdr = (jacknet_packet_header *) rx_packet; | |||
| int rcv_len; | |||
| jack_nframes_t framecnt; | |||
| cache_packet *cpack; | |||
| while (1) | |||
| { | |||
| rcv_len = recv (sockfd, rx_packet, pcache->mtu, MSG_DONTWAIT); | |||
| if (rcv_len < 0) | |||
| return; | |||
| framecnt = ntohl (pkthdr->framecnt); | |||
| //printf( "Got Packet %d\n", framecnt ); | |||
| cpack = packet_cache_get_packet (global_packcache, framecnt); | |||
| cache_packet_add_fragment (cpack, rx_packet, rcv_len); | |||
| } | |||
| } | |||
| int | |||
| packet_cache_retreive_packet( packet_cache *pcache, jack_nframes_t framecnt, char *packet_buf, int pkt_size ) | |||
| { | |||
| int i; | |||
| cache_packet *cpack = NULL; | |||
| for (i = 0; i < pcache->size; i++) { | |||
| if (pcache->packets[i].valid && (pcache->packets[i].framecnt == framecnt)) { | |||
| cpack = &(pcache->packets[i]); | |||
| break; | |||
| } | |||
| } | |||
| if( cpack == NULL ) | |||
| return -1; | |||
| if( !cache_packet_is_complete( cpack ) ) | |||
| return -1; | |||
| // ok. cpack is the one we want and its complete. | |||
| memcpy (packet_buf, cpack->packet_buf, pkt_size); | |||
| cache_packet_reset (cpack); | |||
| return pkt_size; | |||
| } | |||
| // Returns 0 when no valid packet is inside the cache. | |||
| int | |||
| packet_cache_get_next_available_framecnt( packet_cache *pcache, jack_nframes_t expected_framecnt, jack_nframes_t *framecnt ) | |||
| { | |||
| int i; | |||
| jack_nframes_t best_offset = JACK_MAX_FRAMES/2-1; | |||
| int retval = 0; | |||
| for (i = 0; i < pcache->size; i++) | |||
| { | |||
| cache_packet *cpack = &(pcache->packets[i]); | |||
| //printf( "p%d: valid=%d, frame %d\n", i, cpack->valid, cpack->framecnt ); | |||
| if (!cpack->valid || !cache_packet_is_complete( cpack )) { | |||
| //printf( "invalid\n" ); | |||
| continue; | |||
| } | |||
| if( (cpack->framecnt - expected_framecnt) > best_offset ) { | |||
| continue; | |||
| } | |||
| best_offset = cpack->framecnt - expected_framecnt; | |||
| retval = 1; | |||
| if( best_offset == 0 ) | |||
| break; | |||
| } | |||
| if( retval && framecnt ) | |||
| *framecnt = expected_framecnt + best_offset; | |||
| return retval; | |||
| } | |||
| // Returns 0 when no valid packet is inside the cache. | |||
| int | |||
| packet_cache_find_latency( packet_cache *pcache, jack_nframes_t expected_framecnt, jack_nframes_t *framecnt ) | |||
| { | |||
| int i; | |||
| jack_nframes_t best_offset = 0; | |||
| int retval = 0; | |||
| for (i = 0; i < pcache->size; i++) | |||
| { | |||
| cache_packet *cpack = &(pcache->packets[i]); | |||
| //printf( "p%d: valid=%d, frame %d\n", i, cpack->valid, cpack->framecnt ); | |||
| if (!cpack->valid || !cache_packet_is_complete( cpack )) { | |||
| //printf( "invalid\n" ); | |||
| continue; | |||
| } | |||
| if( (cpack->framecnt - expected_framecnt) < best_offset ) { | |||
| continue; | |||
| } | |||
| best_offset = cpack->framecnt - expected_framecnt; | |||
| retval = 1; | |||
| if( best_offset == 0 ) | |||
| break; | |||
| } | |||
| if( retval && framecnt ) | |||
| *framecnt = JACK_MAX_FRAMES - best_offset; | |||
| return retval; | |||
| } | |||
| // fragmented packet IO | |||
| int | |||
| netjack_recvfrom (int sockfd, char *packet_buf, int pkt_size, int flags, struct sockaddr *addr, socklen_t *addr_size, int mtu) | |||
| @@ -427,8 +617,11 @@ netjack_sendto (int sockfd, char *packet_buf, int pkt_size, int flags, struct so | |||
| int fragment_payload_size = mtu - sizeof (jacknet_packet_header); | |||
| if (pkt_size <= mtu) | |||
| if (pkt_size <= mtu) { | |||
| pkthdr = (jacknet_packet_header *) packet_buf; | |||
| pkthdr->fragment_nr = htonl (0); | |||
| sendto(sockfd, packet_buf, pkt_size, flags, addr, addr_size); | |||
| } | |||
| else | |||
| { | |||
| // Copy the packet header to the tx pack first. | |||
| @@ -533,6 +726,9 @@ render_payload_to_jack_ports_float ( void *packet_payload, jack_nframes_t net_pe | |||
| uint32_t *packet_bufX = (uint32_t *)packet_payload; | |||
| if( !packet_payload ) | |||
| return; | |||
| while (node != NULL) | |||
| { | |||
| int i; | |||
| @@ -669,6 +865,9 @@ render_payload_to_jack_ports_16bit (void *packet_payload, jack_nframes_t net_per | |||
| uint16_t *packet_bufX = (uint16_t *)packet_payload; | |||
| if( !packet_payload ) | |||
| return; | |||
| while (node != NULL) | |||
| { | |||
| int i; | |||
| @@ -797,6 +996,9 @@ render_payload_to_jack_ports_8bit (void *packet_payload, jack_nframes_t net_peri | |||
| int8_t *packet_bufX = (int8_t *)packet_payload; | |||
| if( !packet_payload ) | |||
| return; | |||
| while (node != NULL) | |||
| { | |||
| int i; | |||
| @@ -924,14 +1126,9 @@ render_payload_to_jack_ports_celt (void *packet_payload, jack_nframes_t net_peri | |||
| while (node != NULL) | |||
| { | |||
| int i; | |||
| //uint32_t val; | |||
| SRC_DATA src; | |||
| jack_port_t *port = (jack_port_t *) node->data; | |||
| jack_default_audio_sample_t* buf = jack_port_get_buffer (port, nframes); | |||
| float *floatbuf = alloca (sizeof(float) * net_period_down); | |||
| const char *portname = jack_port_type (port); | |||
| if (strncmp(portname, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) | |||
| @@ -939,7 +1136,11 @@ render_payload_to_jack_ports_celt (void *packet_payload, jack_nframes_t net_peri | |||
| // audio port, decode celt data. | |||
| CELTDecoder *decoder = src_node->data; | |||
| celt_decode_float( decoder, packet_bufX, net_period_down, buf ); | |||
| if( !packet_payload ) | |||
| celt_decode_float( decoder, NULL, net_period_down, buf ); | |||
| else | |||
| celt_decode_float( decoder, packet_bufX, net_period_down, buf ); | |||
| src_node = jack_slist_next (src_node); | |||
| } | |||
| else if (strncmp(portname, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) | |||
| @@ -948,7 +1149,8 @@ render_payload_to_jack_ports_celt (void *packet_payload, jack_nframes_t net_peri | |||
| // convert the data buffer to a standard format (uint32_t based) | |||
| unsigned int buffer_size_uint32 = net_period_down / 2; | |||
| uint32_t * buffer_uint32 = (uint32_t*) packet_bufX; | |||
| decode_midi_buffer (buffer_uint32, buffer_size_uint32, buf); | |||
| if( packet_payload ) | |||
| decode_midi_buffer (buffer_uint32, buffer_size_uint32, buf); | |||
| } | |||
| packet_bufX = (packet_bufX + net_period_down); | |||
| node = jack_slist_next (node); | |||
| @@ -963,12 +1165,10 @@ render_jack_ports_to_payload_celt (JSList *playback_ports, JSList *playback_srcs | |||
| JSList *node = playback_ports; | |||
| JSList *src_node = playback_srcs; | |||
| unsigned char *packet_bufX = (uint16_t *)packet_payload; | |||
| unsigned char *packet_bufX = (unsigned char *)packet_payload; | |||
| while (node != NULL) | |||
| { | |||
| SRC_DATA src; | |||
| int i; | |||
| jack_port_t *port = (jack_port_t *) node->data; | |||
| jack_default_audio_sample_t* buf = jack_port_get_buffer (port, nframes); | |||
| const char *portname = jack_port_type (port); | |||
| @@ -90,11 +90,13 @@ struct _packet_cache | |||
| { | |||
| int size; | |||
| cache_packet *packets; | |||
| int mtu; | |||
| }; | |||
| extern packet_cache *global_packcache; | |||
| // fragment cache function prototypes | |||
| // XXX: Some of these are private. | |||
| packet_cache *packet_cache_new(int num_packets, int pkt_size, int mtu); | |||
| void packet_cache_free(packet_cache *pkt_cache); | |||
| @@ -105,13 +107,18 @@ cache_packet *packet_cache_get_free_packet(packet_cache *pkt_cache); | |||
| void cache_packet_reset(cache_packet *pack); | |||
| void cache_packet_set_framecnt(cache_packet *pack, jack_nframes_t framecnt); | |||
| void cache_packet_add_fragment(cache_packet *pack, char *packet_buf, int rcv_len); | |||
| int cache_packet_is_complete(cache_packet *pack); | |||
| int cache_packet_is_complete(cache_packet *pack); | |||
| void packet_cache_drain_socket( packet_cache *pcache, int sockfd ); | |||
| int packet_cache_retreive_packet( packet_cache *pcache, jack_nframes_t framecnt, char *packet_buf, int pkt_size ); | |||
| int packet_cache_get_next_available_framecnt( packet_cache *pcache, jack_nframes_t expected_framecnt, jack_nframes_t *framecnt ); | |||
| int packet_cache_find_latency( packet_cache *pcache, jack_nframes_t expected_framecnt, jack_nframes_t *framecnt ); | |||
| // Function Prototypes | |||
| int netjack_poll(int sockfd, int timeout); | |||
| int netjack_poll_deadline (int sockfd, jack_time_t deadline); | |||
| void netjack_sendto(int sockfd, char *packet_buf, int pkt_size, int flags, struct sockaddr *addr, int addr_size, int mtu); | |||
| int netjack_recvfrom(int sockfd, char *packet_buf, int pkt_size, int flags, struct sockaddr *addr, socklen_t *addr_size, int mtu); | |||
| int netjack_recv(int sockfd, char *packet_buf, int pkt_size, int flags, int mtu); | |||
| int get_sample_size(int bitdepth); | |||
| void packet_header_hton(jacknet_packet_header *pkthdr); | |||
| @@ -122,5 +129,14 @@ void render_payload_to_jack_ports(int bitdepth, void *packet_payload, jack_nfram | |||
| void render_jack_ports_to_payload(int bitdepth, JSList *playback_ports, JSList *playback_srcs, jack_nframes_t nframes, void *packet_payload, jack_nframes_t net_period_up); | |||
| // XXX: This is sort of deprecated: | |||
| // This one waits forever. an is not using ppoll | |||
| int netjack_poll(int sockfd, int timeout); | |||
| // TODO: these are deprecated. | |||
| int netjack_recvfrom(int sockfd, char *packet_buf, int pkt_size, int flags, struct sockaddr *addr, socklen_t *addr_size, int mtu); | |||
| int netjack_recv(int sockfd, char *packet_buf, int pkt_size, int flags, int mtu); | |||
| #endif | |||
| @@ -131,11 +131,11 @@ jack_netsource_LDFLAGS = -lsamplerate @OS_LDFLAGS@ | |||
| jack_netsource_LDADD = $(top_builddir)/libjack/libjack.la | |||
| if HAVE_ALSA | |||
| alsa_in_SOURCES = alsa_in.c | |||
| alsa_in_SOURCES = alsa_in.c time_smoother.c | |||
| alsa_in_LDFLAGS = -lasound -lsamplerate @OS_LDFLAGS@ | |||
| alsa_in_LDADD = $(top_builddir)/libjack/libjack.la | |||
| alsa_out_SOURCES = alsa_out.c | |||
| alsa_out_SOURCES = alsa_out.c time_smoother.c | |||
| alsa_out_LDFLAGS = -lasound -lsamplerate @OS_LDFLAGS@ | |||
| alsa_out_LDADD = $(top_builddir)/libjack/libjack.la | |||
| endif #HAVE_ALSA | |||
| @@ -21,6 +21,7 @@ | |||
| #include "alsa/asoundlib.h" | |||
| #include <samplerate.h> | |||
| #include "time_smoother.h" | |||
| typedef signed short ALSASAMPLE; | |||
| @@ -41,6 +42,8 @@ int jack_sample_rate; | |||
| double current_resample_factor = 1.0; | |||
| time_smoother *smoother; | |||
| // ------------------------------------------------------ commandline parameters | |||
| int sample_rate = 0; /* stream rate */ | |||
| @@ -169,7 +172,7 @@ static int set_swparams(snd_pcm_t *handle, snd_pcm_sw_params_t *swparams, int pe | |||
| return err; | |||
| } | |||
| /* allow the transfer when at least period_size samples can be processed */ | |||
| err = snd_pcm_sw_params_set_avail_min(handle, swparams, period ); | |||
| err = snd_pcm_sw_params_set_avail_min(handle, swparams, 2*period ); | |||
| if (err < 0) { | |||
| printf("Unable to set avail min for capture: %s\n", snd_strerror(err)); | |||
| return err; | |||
| @@ -220,6 +223,7 @@ static snd_pcm_t *open_audiofd( char *device_name, int capture, int rate, int ch | |||
| return handle; | |||
| } | |||
| jack_nframes_t soundcard_frames = 0; | |||
| /** | |||
| * The process callback for this JACK application. | |||
| @@ -231,32 +235,51 @@ int process (jack_nframes_t nframes, void *arg) { | |||
| float *floatbuf, *resampbuf; | |||
| int rlen; | |||
| int err; | |||
| snd_pcm_sframes_t delay; | |||
| snd_pcm_sframes_t delay, absolute_delay; | |||
| jack_nframes_t this_frame_time; | |||
| jack_nframes_t this_soundcard_time; | |||
| int put_back_samples=0; | |||
| int dont_adjust_resampling_factor = 0; | |||
| double a, b; | |||
| { | |||
| snd_pcm_delay( alsa_handle, &delay ); | |||
| this_frame_time = jack_frame_time(client); | |||
| this_soundcard_time = soundcard_frames + delay; | |||
| } | |||
| time_smoother_put( smoother, this_frame_time, this_soundcard_time ); | |||
| // subtract jack_frames_since_cycle_start, to compensate for | |||
| // cpu jitter. | |||
| //absolute_delay = delay; | |||
| //delay = delay - jack_frames_since_cycle_start( client ); | |||
| delay = delay; | |||
| // Do it the hard way. | |||
| // this is for compensating xruns etc... | |||
| if( delay > (target_delay+max_diff) ) { | |||
| ALSASAMPLE *tmp = alloca( (delay-target_delay) * sizeof( ALSASAMPLE ) * num_channels ); | |||
| snd_pcm_readi( alsa_handle, tmp, delay-target_delay ); | |||
| soundcard_frames += (delay-target_delay); | |||
| output_new_delay = (int) delay; | |||
| delay = target_delay; | |||
| dont_adjust_resampling_factor = 1; | |||
| //delay = target_delay; | |||
| // XXX: at least set it to that value. | |||
| current_resample_factor = (double) jack_sample_rate / (double) sample_rate; | |||
| //current_resample_factor = (double) jack_sample_rate / (double) sample_rate; | |||
| } | |||
| if( delay < (target_delay-max_diff) ) { | |||
| snd_pcm_rewind( alsa_handle, target_delay - delay ); | |||
| soundcard_frames -= (target_delay-delay); | |||
| output_new_delay = (int) delay; | |||
| delay = target_delay; | |||
| dont_adjust_resampling_factor = 1; | |||
| //delay = target_delay; | |||
| // XXX: at least set it to that value. | |||
| current_resample_factor = (double) jack_sample_rate / (double) sample_rate; | |||
| //current_resample_factor = (double) jack_sample_rate / (double) sample_rate; | |||
| } | |||
| if( 0 ) { | |||
| /* ok... now we should have target_delay +- max_diff on the alsa side. | |||
| * | |||
| * calculate the number of frames, we want to get. | |||
| @@ -284,17 +307,34 @@ int process (jack_nframes_t nframes, void *arg) { | |||
| double compute_factor = (double) nframes / frlen; | |||
| double diff_value = pow(current_resample_factor - compute_factor, 3) / (double) catch_factor; | |||
| current_resample_factor -= diff_value; | |||
| current_resample_factor = current_resample_factor < 0.25 ? 0.25 : current_resample_factor; | |||
| rlen = ceil( ((double)nframes) / current_resample_factor )+2; | |||
| } | |||
| time_smoother_get_linear_params( smoother, this_frame_time, this_soundcard_time, jack_get_sample_rate(client)/4, | |||
| &a, &b ); | |||
| if( !dont_adjust_resampling_factor ) | |||
| current_resample_factor = b - a/(double)nframes/(double)catch_factor; | |||
| else | |||
| current_resample_factor = b; | |||
| double offset = a; | |||
| double diff_value = b; | |||
| if( (print_counter--) == 0 ) { | |||
| print_counter = 10; | |||
| //printf( "res: %f, \tdiff = %f, \toffset = %f \n", (float)current_resample_factor, (float)diff_value, (float) offset ); | |||
| output_resampling_factor = (float) current_resample_factor; | |||
| output_resampling_factor = (float) current_resample_factor; | |||
| //if( fabs( offset ) > fabs( output_offset ) ) { | |||
| output_diff = (float) diff_value; | |||
| output_offset = (float) offset; | |||
| } | |||
| //} | |||
| if( current_resample_factor < 0.25 ) current_resample_factor = 0.25; | |||
| if( current_resample_factor > 4 ) current_resample_factor = 4; | |||
| rlen = ceil( ((double)nframes) * current_resample_factor )+2; | |||
| assert( rlen > 10 ); | |||
| /* | |||
| * now this should do it... | |||
| @@ -309,13 +349,14 @@ int process (jack_nframes_t nframes, void *arg) { | |||
| again: | |||
| err = snd_pcm_readi(alsa_handle, outbuf, rlen); | |||
| if( err < 0 ) { | |||
| //printf( "err = %d\n", err ); | |||
| printf( "err = %d\n", err ); | |||
| if (xrun_recovery(alsa_handle, err) < 0) { | |||
| //printf("Write error: %s\n", snd_strerror(err)); | |||
| //exit(EXIT_FAILURE); | |||
| } | |||
| goto again; | |||
| } | |||
| soundcard_frames += err; | |||
| if( err != rlen ) { | |||
| //printf( "read = %d\n", rlen ); | |||
| } | |||
| @@ -365,6 +406,7 @@ again: | |||
| //printf( "putback = %d\n", put_back_samples ); | |||
| snd_pcm_rewind( alsa_handle, put_back_samples ); | |||
| soundcard_frames -= put_back_samples; | |||
| return 0; | |||
| } | |||
| @@ -522,6 +564,11 @@ int main (int argc, char *argv[]) { | |||
| if( !max_diff ) | |||
| max_diff = period_size / 2; | |||
| smoother = time_smoother_new( 100 ); | |||
| if( !smoother ) { | |||
| fprintf (stderr, "no memory\n"); | |||
| return 10; | |||
| } | |||
| if ((client = jack_client_new (jack_name)) == 0) { | |||
| @@ -569,12 +616,13 @@ int main (int argc, char *argv[]) { | |||
| } | |||
| while(1) { | |||
| sleep(1); | |||
| usleep(500000); | |||
| if( output_new_delay ) { | |||
| printf( "delay = %d\n", output_new_delay ); | |||
| output_new_delay = 0; | |||
| } | |||
| printf( "res: %f, \tdiff = %f, \toffset = %f \n", output_resampling_factor, output_diff, output_offset ); | |||
| output_offset = 0.0; | |||
| } | |||
| @@ -21,6 +21,7 @@ | |||
| #include "alsa/asoundlib.h" | |||
| #include <samplerate.h> | |||
| #include "time_smoother.h" | |||
| typedef signed short ALSASAMPLE; | |||
| @@ -40,6 +41,9 @@ snd_pcm_t *alsa_handle; | |||
| int jack_sample_rate; | |||
| double current_resample_factor = 1.0; | |||
| int periods_until_stability = 10; | |||
| time_smoother *smoother; | |||
| // ------------------------------------------------------ commandline parameters | |||
| @@ -61,6 +65,7 @@ volatile int output_new_delay = 0; | |||
| volatile float output_offset = 0.0; | |||
| volatile float output_diff = 0.0; | |||
| // Alsa stuff... i dont want to touch this bullshit in the next years.... please... | |||
| static int xrun_recovery(snd_pcm_t *handle, int err) { | |||
| @@ -225,6 +230,7 @@ static snd_pcm_t *open_audiofd( char *device_name, int capture, int rate, int ch | |||
| return handle; | |||
| } | |||
| jack_nframes_t soundcard_frames = 0; | |||
| /** | |||
| * The process callback for this JACK application. | |||
| @@ -237,61 +243,97 @@ int process (jack_nframes_t nframes, void *arg) { | |||
| int rlen; | |||
| int err; | |||
| snd_pcm_sframes_t delay; | |||
| jack_nframes_t this_frame_time; | |||
| jack_nframes_t this_soundcard_time; | |||
| int dont_adjust_resampling_factor = 0; | |||
| double a, b; | |||
| double offset; | |||
| double diff_value; | |||
| snd_pcm_delay( alsa_handle, &delay ); | |||
| this_frame_time = jack_frame_time(client); | |||
| this_soundcard_time = soundcard_frames + delay; | |||
| time_smoother_put( smoother, this_frame_time, this_soundcard_time ); | |||
| // Do it the hard way. | |||
| // this is for compensating xruns etc... | |||
| if( delay > (target_delay+max_diff) ) { | |||
| snd_pcm_rewind( alsa_handle, delay - target_delay ); | |||
| soundcard_frames -= (delay-target_delay); | |||
| output_new_delay = (int) delay; | |||
| snd_pcm_delay( alsa_handle, &delay ); | |||
| //delay = target_delay; | |||
| dont_adjust_resampling_factor = 1; | |||
| //snd_pcm_delay( alsa_handle, &delay ); | |||
| delay = target_delay; | |||
| // XXX: at least set it to that value. | |||
| current_resample_factor = (double) sample_rate / (double) jack_sample_rate; | |||
| //current_resample_factor = (double) sample_rate / (double) jack_sample_rate; | |||
| current_resample_factor = (double) jack_sample_rate / (double) sample_rate; | |||
| periods_until_stability = 10; | |||
| } | |||
| if( delay < (target_delay-max_diff) ) { | |||
| ALSASAMPLE *tmp = alloca( (target_delay-delay) * sizeof( ALSASAMPLE ) * num_channels ); | |||
| memset( tmp, 0, sizeof( ALSASAMPLE ) * num_channels * (target_delay-delay) ); | |||
| snd_pcm_writei( alsa_handle, tmp, target_delay-delay ); | |||
| soundcard_frames += (target_delay-delay); | |||
| output_new_delay = (int) delay; | |||
| snd_pcm_delay( alsa_handle, &delay ); | |||
| //delay = target_delay; | |||
| dont_adjust_resampling_factor = 1; | |||
| //snd_pcm_delay( alsa_handle, &delay ); | |||
| delay = target_delay; | |||
| // XXX: at least set it to that value. | |||
| current_resample_factor = (double) sample_rate / (double) jack_sample_rate; | |||
| //current_resample_factor = (double) sample_rate / (double) jack_sample_rate; | |||
| current_resample_factor = (double) jack_sample_rate / (double) sample_rate; | |||
| periods_until_stability = 10; | |||
| } | |||
| /* ok... now we should have target_delay +- max_diff on the alsa side. | |||
| * | |||
| * calculate the number of frames, we want to get. | |||
| */ | |||
| double resamp_rate = (double)jack_sample_rate / (double)sample_rate; // == nframes / alsa_samples. | |||
| double request_samples = nframes / resamp_rate; //== alsa_samples; | |||
| //double request_samples = nframes * current_resample_factor; //== alsa_samples; | |||
| double offset = delay - target_delay; | |||
| //if( periods_until_stability ) { | |||
| if( 1 ) { | |||
| double resamp_rate = (double)jack_sample_rate / (double)sample_rate; // == nframes / alsa_samples. | |||
| double request_samples = nframes / resamp_rate; //== alsa_samples; | |||
| //double request_samples = nframes * current_resample_factor; //== alsa_samples; | |||
| //double frlen = request_samples - offset / catch_factor; | |||
| double frlen = request_samples - offset; | |||
| offset = delay - target_delay; | |||
| double compute_factor = frlen / (double) nframes; | |||
| //double frlen = request_samples - offset / catch_factor; | |||
| double frlen = request_samples - offset; | |||
| double diff_value = pow(current_resample_factor - compute_factor, 3) / (double) catch_factor; | |||
| current_resample_factor -= diff_value; | |||
| current_resample_factor = current_resample_factor < 0.25 ? 0.25 : current_resample_factor; | |||
| rlen = ceil( ((double)nframes) * current_resample_factor ) + 2; | |||
| double compute_factor = frlen / (double) nframes; | |||
| //double compute_factor = (double) nframes / frlen; | |||
| if( (print_counter--) == 0 ) { | |||
| print_counter = 10; | |||
| //printf( "res: %f, \tdiff = %f, \toffset = %f \n", (float)current_resample_factor, (float)diff_value, (float) offset ); | |||
| output_resampling_factor = (float) current_resample_factor; | |||
| output_diff = (float) diff_value; | |||
| output_offset = (float) offset; | |||
| diff_value = pow(current_resample_factor - compute_factor, 3) / (double) catch_factor; | |||
| current_resample_factor -= diff_value; | |||
| periods_until_stability -= 1; | |||
| } | |||
| else | |||
| { | |||
| time_smoother_get_linear_params( smoother, this_frame_time, this_soundcard_time, jack_get_sample_rate(client)/4, | |||
| &a, &b ); | |||
| if( dont_adjust_resampling_factor ) { | |||
| current_resample_factor = 1.0/( b - a/(double)nframes/(double)catch_factor ); | |||
| //double delay_diff = (double)delay - (double)target_delay; | |||
| //current_resample_factor = 1.0/( b + a/(double)nframes - delay_diff/(double)nframes/(double)catch_factor ); | |||
| } else | |||
| current_resample_factor = 1.0/b; | |||
| offset = delay - target_delay; | |||
| diff_value = b; | |||
| } | |||
| output_resampling_factor = (float) current_resample_factor; | |||
| output_diff = (float) diff_value; | |||
| output_offset = (float) offset; | |||
| if( current_resample_factor < 0.25 ) current_resample_factor = 0.25; | |||
| if( current_resample_factor > 4 ) current_resample_factor = 4; | |||
| rlen = ceil( ((double)nframes) * current_resample_factor )+2; | |||
| assert( rlen > 10 ); | |||
| /* | |||
| * now this should do it... | |||
| */ | |||
| @@ -323,10 +365,8 @@ int process (jack_nframes_t nframes, void *arg) { | |||
| src.output_frames = rlen; | |||
| src.end_of_input = 0; | |||
| //src.src_ratio = (float) frlen / (float) nframes; | |||
| src.src_ratio = current_resample_factor; | |||
| //src_set_ratio( src_state, src.src_ratio ); | |||
| src_process( src_state, &src ); | |||
| for (i=0; i < rlen; i++) { | |||
| @@ -343,13 +383,15 @@ int process (jack_nframes_t nframes, void *arg) { | |||
| again: | |||
| err = snd_pcm_writei(alsa_handle, outbuf, src.output_frames_gen); | |||
| if( err < 0 ) { | |||
| //printf( "err = %d\n", err ); | |||
| printf( "err = %d\n", err ); | |||
| if (xrun_recovery(alsa_handle, err) < 0) { | |||
| //printf("Write error: %s\n", snd_strerror(err)); | |||
| //exit(EXIT_FAILURE); | |||
| } | |||
| goto again; | |||
| } | |||
| soundcard_frames += err; | |||
| // if( err != rlen ) { | |||
| // printf( "write = %d\n", rlen ); | |||
| // } | |||
| @@ -513,6 +555,11 @@ int main (int argc, char *argv[]) { | |||
| if( !max_diff ) | |||
| max_diff = period_size / 2; | |||
| smoother = time_smoother_new( 100 ); | |||
| if( !smoother ) { | |||
| fprintf (stderr, "no memory\n"); | |||
| return 10; | |||
| } | |||
| if ((client = jack_client_new (jack_name)) == 0) { | |||
| @@ -560,7 +607,7 @@ int main (int argc, char *argv[]) { | |||
| } | |||
| while(1) { | |||
| sleep(1); | |||
| usleep(500000); | |||
| if( output_new_delay ) { | |||
| printf( "delay = %d\n", output_new_delay ); | |||
| output_new_delay = 0; | |||
| @@ -238,24 +238,13 @@ process (jack_nframes_t nframes, void *arg) | |||
| packet_bufX = packet_buf + sizeof (jacknet_packet_header) / sizeof (uint32_t); | |||
| /* ---------- Receive ---------- */ | |||
| // New Receive Code: | |||
| if (reply_port) | |||
| size = netjack_recv (insockfd, (char *) packet_buf, rx_bufsize, MSG_DONTWAIT, mtu); | |||
| packet_cache_drain_socket(global_packcache, insockfd); | |||
| else | |||
| size = netjack_recv (outsockfd, (char *) packet_buf, rx_bufsize, MSG_DONTWAIT, mtu); | |||
| packet_header_ntoh (pkthdr); | |||
| /* Loop till we get the right packet at the right momment */ | |||
| while (size == rx_bufsize && (framecnt - pkthdr->framecnt) > latency) | |||
| { | |||
| //printf ("Frame %d \tLate packet received with a latency of %d frames (expected frame %d, got frame %d)\n", framecnt, framecnt - pkthdr->framecnt, framecnt - latency, pkthdr->framecnt); | |||
| //printf ("Frame %d \tLate packet received with a latency of %d frames\n", framecnt, framecnt - pkthdr->framecnt); | |||
| packet_cache_drain_socket(global_packcache, outsockfd); | |||
| if (reply_port) | |||
| size = netjack_recv (insockfd, (char *) packet_buf, rx_bufsize, MSG_DONTWAIT, mtu); | |||
| else | |||
| size = netjack_recv (outsockfd, (char *) packet_buf, rx_bufsize, MSG_DONTWAIT, mtu); | |||
| packet_header_ntoh (pkthdr); | |||
| } | |||
| size = packet_cache_retreive_packet( global_packcache, framecnt - latency, (char *)packet_buf, rx_bufsize ); | |||
| /* First alternative : we received what we expected. Render the data | |||
| * to the JACK ports so it can be played. */ | |||
| @@ -273,7 +262,7 @@ process (jack_nframes_t nframes, void *arg) | |||
| // printf ("Frame %d \tSync has been set\n", framecnt); | |||
| state_currentframe = framecnt; | |||
| state_latency = framecnt - pkthdr->framecnt; | |||
| //state_latency = framecnt - pkthdr->framecnt; | |||
| state_connected = 1; | |||
| sync_state = pkthdr->sync_state; | |||
| } | |||
| @@ -282,9 +271,13 @@ process (jack_nframes_t nframes, void *arg) | |||
| * to the ouput ports */ | |||
| else | |||
| { | |||
| jack_nframes_t latency_estimate; | |||
| if( packet_cache_find_latency( global_packcache, framecnt, &latency_estimate ) ) | |||
| state_latency = latency_estimate; | |||
| // Set the counters up. | |||
| state_currentframe = framecnt; | |||
| state_latency = framecnt - pkthdr->framecnt; | |||
| //state_latency = framecnt - pkthdr->framecnt; | |||
| state_netxruns += 1; | |||
| //printf ("Frame %d \tPacket missed or incomplete (expected: %d bytes, got: %d bytes)\n", framecnt, rx_bufsize, size); | |||
| @@ -329,11 +322,11 @@ process (jack_nframes_t nframes, void *arg) | |||
| pkthdr->mtu = mtu; | |||
| packet_header_hton (pkthdr); | |||
| if (cont_miss < 10) | |||
| if (cont_miss < 2*latency+5) | |||
| netjack_sendto (outsockfd, (char *) packet_buf, tx_bufsize, 0, &destaddr, sizeof (destaddr), mtu); | |||
| // else if (cont_miss >= 10 && cont_miss <= 50) | |||
| // printf ("Frame %d \tToo many packets missed (%d). We have stopped sending data\n", framecnt, cont_miss); | |||
| else if (cont_miss > 50) | |||
| else if (cont_miss > 50+5*latency) | |||
| { | |||
| state_connected = 0; | |||
| //printf ("Frame %d \tRealy too many packets missed (%d). Let's reset the counter\n", framecnt, cont_miss); | |||