/* TODO: Move UDP socket creation to connection handler thread * Faced a bug when capture thread executed before send_audio * thread had established UDP socket and as a result, server * lost AUDIO_RQST from client */ int send_audio(struct connection_data *_conn) { /* send data over the UDP socket */ struct connection_data conn = *_conn; int sockfd = conn.udp_sock_rx; struct sockaddr_in other, own; short audio_samples[SPEEX_FRAME_SIZE]; char buffer[512]; char compressed[SPEEX_FRAME_SIZE]; int addrlen; int rc; int i; /* variables for speex */ SpeexBits bits; void *state; /* For holding encoder state */ int quality; int nbytes, count; dbg("Preparing speex for compression"); state = speex_encoder_init(&speex_nb_mode); /* Set the quality to 8 (15 kbps) */ quality = 8; speex_encoder_ctl(state, SPEEX_SET_QUALITY, &quality); speex_bits_init(&bits); dbg("Preparing to send audio over UDP socket"); own = conn.own; other = conn.other; other.sin_port = htons(8889); addrlen = sizeof other; /* send data here */ /* TODO: How to end the send? */ //dbg("Sending audio data to other side \n"); memset(compressed, 0, sizeof compressed); memset(buffer, 0, sizeof buffer); printf("Trying data send\n"); /* Instead of multiple sends over socket, compress the complete audio buffer size * of data, each encoding results in 38 bytes, so a 512 bytes transmit buffer * can accomodate over 512 / 38 ~ 13 160 bytes speex frames. We are sending only * 5 (i.e 800 / 160) speex frames for our audio buffer of 800 frames */ for (i = 0, count = 0; i < 5; i++) { /* if read is unsuccessful, wait for capture thread * to write audio data to sbuff */ rc = ring_read(sbuff, (char *)audio_samples, sizeof audio_samples); printf("Read %d bytes from tx circular buffer \n", rc); speex_bits_reset(&bits); /* Encode here */ speex_encode_int(state, audio_samples, &bits); /* Write the encoded bits to array of bytes so that they can be written */ nbytes = speex_bits_write(&bits, compressed, sizeof compressed); memcpy(buffer + i * 38, compressed, nbytes); count += nbytes; //printf("Size of compressed data: %d \n", nbytes); //printf("Size of audio_samples: %d \n", sizeof audio_samples); //printf("Iteration no : %d \n", i + 1); } if ((rc =sendto(sockfd, buffer, sizeof buffer, 0, (struct sockaddr *)&other, addrlen)) < 0) { fprintf(stderr, "Unable to send data to other side \n"); } else printf("Data sent: %d bytes\n", rc); dbg("Freeing up speex resources"); /* Destroy the encoder state */ speex_encoder_destroy(state); /* Destroy the bits-packing */ speex_bits_destroy(&bits); #if 0 send_sock_close: dbg("Closing UDP socket connection"); /* stop reception and transmission */ if (rc = shutdown(sockfd, 2)) { fprintf(stderr, "Unable to end connection: %s \n", strerror(errno)); } /* close the socket so that it can be reused */ close(sockfd); audio_end: pthread_exit(NULL); #endif }
void *receive_audio(void *data) { struct connection_data conn = *((struct connection_data *)data); struct sockaddr_in other = conn.other; char buffer[512]; char compressed[SPEEX_FRAME_SIZE]; short audio_samples[SPEEX_FRAME_SIZE]; int sockfd = conn.udp_sock_rx; /* Descriptor for UDP socket */ /* receive data from socket, add to buffer */ int addrlen = sizeof other; int rc; /* variables for speex */ SpeexBits bits; void *state; /* For holding encoder state */ int tmp; int nbytes; int i; int ret; unsigned int rate = 8000; int size; short playback_samples[SAMPLES_PER_PERIOD]; int fd; int frame_size = 2; snd_pcm_t *handle; snd_pcm_hw_params_t *params; /* write many data at a time to device */ /* the value of 5512 comes from aplay, investigate * why it is so */ int buffer_size = SAMPLES_PER_PERIOD * sizeof(short); printf("rate is =%d \n", rate); dbg("Preparing audio playback"); ret = voip_init_pcm(&handle, ¶ms, &buffer_size, &rate, PLAYBACK); if (ret < 0) { fprintf(stderr, "Failed to prepare audio system\n"); goto rcv_audio_end; } printf("Pointer address to handle=%p \n", &handle); printf("Pointer to handle=%p \n", handle); printf("Pointer to params=%p \n", params); dbg("Preparing speex for de-compression"); state = speex_decoder_init(&speex_nb_mode); tmp = 1; speex_decoder_ctl(state, SPEEX_SET_ENH, &tmp); speex_bits_init(&bits); while(1) { memset(audio_samples, 0, sizeof audio_samples); memset(compressed, 0, sizeof compressed); memset(buffer, 0, sizeof buffer); printf("Waiting for data\n"); if ((rc = recvfrom(sockfd, buffer, sizeof buffer, 0, (struct sockaddr *)&other, &addrlen)) < 0) { fprintf(stderr, "Unable to receive audio data: %s \n", strerror(errno)); goto rcv_sock_close; } printf("Received %d compressed bytes on UDP socket \n", rc); for (i = 0; i < 5; i++) { speex_bits_reset(&bits); /* each encoded speex frame takes 38 bytes */ memcpy(compressed, buffer + i * 38, 38); speex_bits_read_from(&bits, compressed, 38); /* Decode here */ speex_decode_int(state, &bits, audio_samples); ring_write(rbuff, (char *)audio_samples, sizeof audio_samples); } ret = ring_read(rbuff, (char *)audio_samples, buffer_size); if ( ret != buffer_size) { fprintf(stderr, "short read: read %d bytes \n", ret); } printf("Playing audio \n"); /* write frames in one period to device */ ret = voip_playback(handle, buffer_size / frame_size, audio_samples); } voip_end_pcm(handle); /* Destroy the encoder state */ speex_decoder_destroy(state); /* Destroy the bits-packing */ speex_bits_destroy(&bits); rcv_sock_close: close(sockfd); rcv_audio_end: pthread_exit(NULL); }
int main(int argc, char **argv) { if (argc == 1) { signal(SIGCHLD, SIG_IGN); int pid = remote_spawn(argv[0]); if (pid < 1) { fprintf(stderr, "failed to spawn remote\n"); return 1; } state.remote = 1; for (int i = 0; i < RACE_COUNT; i++) { glRectf(0, 0, 1, 1); } int status = 0; waitpid(pid, &status, 0); if (WEXITSTATUS(status) || WTERMSIG(status)) { fprintf(stderr, "Error from libgl_remote: %d\n", status); return 1; } } else { ring_t _ring = {0}; ring_t *ring = &_ring; ring_setup(ring, strtol(argv[1]+1, NULL, 10)); if (ring_server_handshake(ring)) { fprintf(stderr, "Error doing server handshake\n"); return 2; } for (int i = 0; i < RACE_COUNT - 1; i++) { // fprintf(stderr, "remote %d\n", i); // fprintf(stderr, "reading retsize\n"); void *buf = ring_read(ring, NULL); uint32_t retsize = *(uint32_t *)buf; // fprintf(stderr, "retsize=%d\n", retsize); if (retsize != 0) { unsigned char *c = buf; fprintf(stderr, "ERROR: Expected retsize=0. Got: %d\n", retsize); fprintf(stderr, "read=%d, mark=%d, call=%d, write=%d, %02X%02X %02X%02X %02x%02x %02x%02x\n", *ring->read, *ring->mark, (uintptr_t)c - (uintptr_t)ring->buf, *ring->write, c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]); kill(getppid(), SIGTERM); return 1; } // fprintf(stderr, "reading call\n"); packed_call_t *call = buf + sizeof(uint32_t); unsigned char *c = call; // fprintf(stderr, "read=%d, mark=%d, call=%d, write=%d, %02X%02X %02X%02X %02x%02x %02x%02x %d\n", *ring->read, *ring->mark, (uintptr_t)c - (uintptr_t)ring->buf, *ring->write, c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], call->index); if (call->index != REMOTE_BLOCK_DRAW) { fprintf(stderr, "ERROR: Expected REMOTE_BLOCK_DRAW. Got: %d\n", call->index); fprintf(stderr, "read=%d, mark=%d, call=%d, write=%d, %02X%02X %02X%02X %02x%02x %02x%02x %d\n", *ring->read, *ring->mark, (uintptr_t)c - (uintptr_t)ring->buf, *ring->write, c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], call->index); kill(getppid(), SIGTERM); return 1; } block_t *block = remote_read_block(ring, (void *)call); // fprintf(stderr, "block->len: %d\n", block->len); if (block->len != 4) { fprintf(stderr, "ERROR: Expected block->len == 4, got: %d\n", block->len); fprintf(stderr, "read=%d, mark=%d, call=%d, write=%d, %02X%02X %02X%02X %02x%02x %02x%02x %d\n", *ring->read, *ring->mark, (uintptr_t)c - (uintptr_t)ring->buf, *ring->write, c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], call->index); kill(getppid(), SIGTERM); return 1; } ring_advance(ring); } } return 0; }
void ring_read_into(ring_t *ring, void *dst) { size_t size; void *data = ring_read(ring, &size); memcpy(dst, data, size); }
static int tcpclient_buffer_read(urg_tcpclient_t* cli, char* data, int size) { return ring_read(&cli->rb, data, size); }
static void writeout_ext(multiplex_t *mx, int n) { uint8_t outbuf[3000]; int written=0; unsigned int length=0; int nlength=0; uint64_t pts, dpts=0; int newpts=0; int nframes=1; int ac3_off=0; int rest_data = 5; int type = mx->ext[n].type; ringbuffer *airbuffer = &mx->index_extrbuffer[n]; dummy_buffer *dbuf = &mx->ext[n].dbuf; uint64_t adelay = mx->ext[n].pts_off; uint64_t *apts = &mx->ext[n].pts; index_unit *aiu = &mx->ext[n].iu; switch (type){ case MPEG_AUDIO: #ifdef OUT_DEBUG fprintf(stderr,"writing AUDIO%d pack\n",n); #endif break; case AC3: #ifdef OUT_DEBUG fprintf(stderr,"writing AC3%d pack\n",n); #endif rest_data = 1; // 4 bytes AC3 header break; default: return; } if (mx->finish != 2 && dummy_space(dbuf) < mx->data_size + rest_data){ return; } pts = uptsdiff( aiu->pts + mx->audio_delay, adelay ); *apts = pts; length = aiu->length; if (length < aiu->framesize){ newpts = 1; ac3_off = length; } dummy_add(dbuf, pts, aiu->length); #ifdef OUT_DEBUG fprintf(stderr,"start: %d stop: %d (%d) length %d ", aiu->start, (aiu->start+aiu->length), aiu->length, length); printpts(*apts); printpts(aiu->pts); printpts(mx->audio_delay); printpts(adelay); printpts(pts); fprintf(stderr,"\n"); #endif while (!mx->is_ts && length < mx->data_size + rest_data){ if (ring_read(airbuffer, (uint8_t *)aiu, sizeof(index_unit)) > 0){ dpts = uptsdiff(aiu->pts +mx->audio_delay, adelay ); if (newpts){ pts = dpts; newpts=0; } length+= aiu->length; if (length < mx->data_size + rest_data) dummy_add(dbuf, dpts, aiu->length); *apts = dpts; nframes++; #ifdef OUT_DEBUG fprintf(stderr,"start: %d stop: %d (%d) length %d ", aiu->start, (aiu->start+aiu->length), aiu->length, length); printpts(*apts); printpts(aiu->pts); printpts(mx->audio_delay); printpts(adelay); fprintf(stderr,"\n"); #endif } else if (mx->finish){ break; } else if (mx->fill_buffers(mx->priv, mx->finish)< 0) { fprintf(stderr,"error in writeout ext\n"); exit(1); } } nlength = length; switch (type) { case MPEG_AUDIO: if(mx->is_ts) written = write_audio_ts( mx->ext[n].strmnum, pts, outbuf, &nlength, newpts ? 0 : PTS_ONLY, &mx->extrbuffer[n]); else written = write_audio_pes( mx->pack_size, mx->extcnt, mx->ext[n].strmnum, pts, mx->SCR, mx->muxr, outbuf, &nlength, PTS_ONLY, &mx->extrbuffer[n]); break; case AC3: if(mx->is_ts) written = write_ac3_ts(mx->ext[n].strmnum, pts, outbuf, &nlength, newpts ? 0 : PTS_ONLY, mx->ext[n].frmperpkt, &mx->extrbuffer[n]); else written = write_ac3_pes( mx->pack_size, mx->extcnt, mx->ext[n].strmnum, pts, mx->SCR, mx->muxr, outbuf, &nlength, PTS_ONLY, nframes, ac3_off, &mx->extrbuffer[n]); break; } length -= nlength; write(mx->fd_out, outbuf, written); dummy_add(dbuf, dpts, aiu->length-length); aiu->length = length; aiu->start = ring_rpos(&mx->extrbuffer[n]); if (aiu->length == 0){ get_next_ext_unit(mx, aiu, n); } else { //estimate next pts based on bitrate of stream and data written aiu->pts = uptsdiff(aiu->pts + ((nlength*aiu->ptsrate)>>8), 0); } *apts = uptsdiff(aiu->pts + mx->audio_delay, adelay); #ifdef OUT_DEBUG if ((int64_t)*apts < 0) fprintf(stderr,"SCHEISS "); fprintf(stderr,"APTS"); printpts(*apts); printpts(aiu->pts); printpts(mx->audio_delay); printpts(adelay); fprintf(stderr,"\n"); #endif if (mx->fill_buffers(mx->priv, mx->finish)< 0) { fprintf(stderr,"error in writeout ext\n"); exit(1); } }