int main (int argc, char *argv[]) { struct rtp *session; int rx_port, tx_port, fd; uint32_t read_size, packet_size, number_of_packet; uint8_t buff[BUFFSIZE]; off_t cur_pos; char *ip_addr; char filename[1024]; int c; struct hostent *h; struct utsname myname; #ifdef HAVE_SRTP #else void *srtp_data; #endif unsigned int extra_len; int do_auth = 1, do_encrypt = 1; ssize_t readit; ssize_t sendit; int do_rtcp = false; // Setting of default session if(uname(&myname) < 0){ fprintf(stderr,"uname\n"); exit(1); } if((h = gethostbyname(myname.nodename)) == NULL) { herror("gethostbyname"); exit(1); } ip_addr = strdup(inet_ntoa(*((struct in_addr *)h->h_addr))); rx_port = 15002; tx_port = 15000; // Option opterr = 0; while((c = getopt(argc, argv, "acdehi:r:t:f:")) != -1){ switch (c) { case 'a': do_auth = 0; break; case 'c': do_rtcp = 1; break; case 'd': dump_pak = true; break; case 'e': do_encrypt = 0; break; case 'h': printf("Usage: ./test_rtp_client -i <IP_Addr> -r <rx_port> -t <tx_port> -f <filename>\n"); printf("Default values are as follows...\n"); printf("ip_addr = %s\n", ip_addr); printf("rx_port = %d\n", rx_port); printf("tx_port = %d\n", tx_port); printf("Filename = %s\n", filename); exit(-1); case 'i': strcpy(ip_addr, optarg); break; case 'r': rx_port = atoi(optarg); break; case 't': tx_port = atoi(optarg); break; case 'f': strcpy(filename,optarg); break; case '?': printf("usage: ./test_rtp_client -i <IP_Addr> -r <rx_port> -t <tx_port> -f <filename>\n"); exit(1); } } if (optind < argc) { for(; optind < argc; optind++) { printf("error->%s(#%d): put -[i|r|t|f] \n", argv[optind],optind-1); } exit(1); } // display session information printf("\n-Session Information-\n"); printf(" ip_addr = %s\n", ip_addr); printf(" rx_port = %d\n", rx_port); printf(" tx_port = %d\n", tx_port); printf(" filename = %s\n", filename); printf("Press Return key..."); // getchar(); // Open Original File to compare with received file if((fd = open(filename, O_RDONLY)) == -1){ perror(filename); exit(1); } rtp_stream_params_t rsp; rtp_default_params(&rsp); rsp.rtp_addr = ip_addr; rsp.rtp_rx_port = rx_port; rsp.rtp_tx_port = tx_port; rsp.rtp_ttl = TTL; rsp.rtcp_bandwidth = RTCP_BW; rsp.rtp_callback = c_rtp_callback; rsp.transmit_initial_rtcp = 1; if ( (session = rtp_init_stream(&rsp) ) == NULL){ exit(-1); } rtp_set_my_ssrc(session,OUR_SSRC); #ifdef HAVE_SRTP /////////// start will //set NULL security services //uint32_t ssrc = 0xdeadbeef; /* ssrc value hardcoded for now */ srtp_policy_t policy; char key[64]; char keystr[128]; uint ix; #if 1 strcpy(keystr, "c1eec3717da76195bb878578790af71c4ee9f859e197a414a78d5abc7451"); hex_string_to_octet_string(key, keystr, 60); #else memset(key, 0, sizeof(key)); #endif for (ix = 0; ix < 30; ix++) { printf("%02x ", key[ix]); } printf("\n"); #if 0 // NULL cipher policy.key = (uint8_t *) key; policy.ssrc.type = ssrc_any_outbound; //ssrc_specific; policy.ssrc.value = 0x96;//OUR_SSRC; policy.rtp.cipher_type = NULL_CIPHER; policy.rtp.cipher_key_len = 0; policy.rtp.auth_type = NULL_AUTH; policy.rtp.auth_key_len = 0; policy.rtp.auth_tag_len = 0; policy.rtp.sec_serv = sec_serv_none; policy.rtcp.cipher_type = NULL_CIPHER; policy.rtcp.cipher_key_len = 0; policy.rtcp.auth_type = NULL_AUTH; policy.rtcp.auth_key_len = 0; policy.rtcp.auth_tag_len = 0; policy.rtcp.sec_serv = sec_serv_none; policy.next = NULL; #else //confidentiality only, no auth crypto_policy_set_aes_cm_128_null_auth(&policy.rtp); crypto_policy_set_rtcp_default(&policy.rtcp); policy.ssrc.type = ssrc_any_outbound; policy.key = (uint8_t *) key; policy.next = NULL; policy.rtp.sec_serv = sec_serv_conf;//sec_servs; policy.rtcp.sec_serv = sec_serv_none; /* we don't do RTCP anyway */ #endif err_status_t status; printf("ABOUT TO SRTP_INIT\n"); status = srtp_init(); if (status) { printf("error: srtp initialization failed with error code %d\n", status); exit(1); } printf("ABOUT TO SRTP_CREAT\n"); srtp_ctx_t *srtp_ctx = NULL; status = srtp_create(&srtp_ctx, &policy); if (status) { printf("error: srtp_create() failed with code %d\n", status); exit(1); } printf("DONE WITH SRTP_CREATE\n"); extra_len = 0; #else extra_len = 0; srtp_data = NULL; #endif rtp_encryption_params_t params; params.rtp_encrypt = ENCRYPT_FUNCTION; params.rtcp_encrypt = RTCP_ENCRYPT_FUNCTION; params.rtp_decrypt = DECRYPT_FUNCTION; params.rtcp_decrypt = RTCP_DECRYPT_FUNCTION; params.userdata = srtp_data; params.rtp_auth_alloc_extra = params.rtcp_auth_alloc_extra = 0; rtp_set_encryption_params(session, ¶ms); if (do_rtcp) { rtcp_file = fopen("server.rtcp", FOPEN_WRITE_BINARY); } cur_pos = 0; packet_size = 64; number_of_packet = 0; while(1) { // change BUFFSIZE to be an incrementing value from 64 to 1450 if(packet_size > 1450) packet_size = 725; readit = read(fd, buff, packet_size); if (readit < 0) { perror("file read"); exit(1); } read_size = readit; //int buflen = readit; if (read_size == 0) break; //printf("about to protect\n"); #if 0 sendit = rtp_send_data(session, cur_pos, 97,//pt 0,//m 0,//cc NULL, //csrc[], buff,//data read_size,//data_len NULL,//*extn 0, 0); #else { struct iovec iov[2]; iov[0].iov_len = read_size % 48; if (iov[0].iov_len == 0) iov[0].iov_len = 1; iov[0].iov_base = buff; iov[1].iov_len = read_size - iov[0].iov_len; iov[1].iov_base = buff + iov[0].iov_len; sendit = rtp_send_data_iov(session, cur_pos, 97, 0, 0, NULL, iov, read_size > iov[0].iov_len ? 2 : 1, NULL, 0, 0, 0); } #endif if (sendit < 0) { printf("rtp_send_data error\n"); exit(1); } if (do_rtcp) rtp_send_ctrl(session, cur_pos, NULL); printf("set timestamp = "U64", size %u\n", cur_pos, read_size); cur_pos += read_size; packet_size++; number_of_packet++; //rtp_periodic(); //rtp_send_ctrl(session,cur_pos,NULL); rtp_update(session); // Some sort of sleep here... usleep(2 * 1000); } printf("I've sent %d RTP packets!\n\n", number_of_packet); close(fd); if (rtcp_file != NULL) fclose(rtcp_file); rtp_done(session); return 0; }
void * os_sound_start_thread (void *_ca) { int i; call_t *ca = (call_t *) _ca; struct timeval timeout; uint32_t rtp_ts, round; uint8_t mulaw_buffer[MULAW_BYTES * 16]; int mulaw_buffer_pos; #ifdef USE_PCM char data_out[MULAW_BYTES * 2 * 16]; #endif fprintf (stderr, "Sending and listening to "); fprintf (stderr, "%s port %d (local SSRC = 0x%08x)\n", rtp_get_addr (ca->rtp_session), rtp_get_rx_port (ca->rtp_session), rtp_my_ssrc (ca->rtp_session)); round = 0; mulaw_buffer_pos = 0; while (ca->enable_audio != -1) { struct timeval t_beg; struct timeval t_end; struct timeval interval; gettimeofday (&t_beg, NULL); round++; /* original line rtp_ts = round * MULAW_MS; */ rtp_ts = round * MULAW_BYTES; if (ca->local_sendrecv != _RECVONLY) { if (mulaw_buffer_pos < MULAW_BYTES * 4) { /* Send control packets */ rtp_send_ctrl (ca->rtp_session, rtp_ts, NULL); /* Send data packets */ #ifdef USE_PCM i = read (ca->fd, data_out, MULAW_BYTES * 4); if (ca->local_sendrecv == _SENDRECV || ca->local_sendrecv == _RECVONLY) { } else { if (i < MULAW_BYTES * 4) { memset (data_out, 0, MULAW_BYTES * 4); OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "restarting: %i\n", i)); close (ca->fd); /* send a wav file! */ ca->fd = open (ca->wav_file, O_RDONLY); if (ca->fd < 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "Could not open wav file: %s\n", ca->wav_file)); ca->fd = -1; break; } i = read (ca->fd, data_out, MULAW_BYTES * 4); } } if (ca->payload == 8) /* A-Law */ alaw_enc (data_out, mulaw_buffer + mulaw_buffer_pos, i); if (ca->payload == 0) /* Mu-Law */ mulaw_enc (data_out, mulaw_buffer + mulaw_buffer_pos, i); i = i / 2; mulaw_buffer_pos = mulaw_buffer_pos + i; #else memset (mulaw_buffer + mulaw_buffer_pos, 0, MULAW_BYTES * 2); i = read (ca->fd, mulaw_buffer + mulaw_buffer_pos, MULAW_BYTES * 2); /* ?? */ mulaw_buffer_pos = mulaw_buffer_pos + i; #endif } i = 0; if (mulaw_buffer_pos >= MULAW_BYTES) { i = rtp_send_data (ca->rtp_session, rtp_ts, ca->payload, 0, 0, 0, (char *) mulaw_buffer, MULAW_BYTES, 0, 0, 0); memmove (mulaw_buffer, mulaw_buffer + MULAW_BYTES, MULAW_BYTES * 15); mulaw_buffer_pos = mulaw_buffer_pos - MULAW_BYTES; } } else { /* Send control packets */ rtp_send_ctrl (ca->rtp_session, rtp_ts, NULL); } /* Receive control and data packets */ timeout.tv_sec = 0; timeout.tv_usec = 0; i = rtp_recv (ca->rtp_session, &timeout, rtp_ts); /* State maintenance */ rtp_update (ca->rtp_session); gettimeofday (&t_end, NULL); /* make a diff between t_beg and t_end */ interval.tv_sec = t_end.tv_sec - t_beg.tv_sec; interval.tv_usec = t_end.tv_usec - t_beg.tv_usec; if (interval.tv_usec < 0) { interval.tv_usec += 1000000L; --interval.tv_sec; } interval.tv_usec = (MULAW_MS * 1000 - interval.tv_usec); if (interval.tv_usec < 0) { interval.tv_usec += 1000000L; --interval.tv_sec; } if (interval.tv_sec < 0) { interval.tv_sec = 0; interval.tv_usec = 0; } select (0, NULL, NULL, NULL, &interval); } return NULL; }
bool toxav_audio_send_frame(ToxAV *av, uint32_t friend_number, const int16_t *pcm, size_t sample_count, uint8_t channels, uint32_t sampling_rate, TOXAV_ERR_SEND_FRAME *error) { uint64_t start_time = current_time_monotonic(); uint64_t delta = start_time; LOGGER_DEBUG ("Starting time: %llu", start_time); TOXAV_ERR_SEND_FRAME rc = TOXAV_ERR_SEND_FRAME_OK; ToxAVCall *call; if (m_friend_exists(av->m, friend_number) == 0) { rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND; goto END; } if (pthread_mutex_trylock(av->mutex) != 0) { rc = TOXAV_ERR_SEND_FRAME_SYNC; goto END; } call = call_get(av, friend_number); if (call == NULL || !call->active || call->msi_call->state != msi_CallActive) { pthread_mutex_unlock(av->mutex); rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL; goto END; } if (call->audio_bit_rate == 0 || !(call->msi_call->self_capabilities & msi_CapSAudio) || !(call->msi_call->peer_capabilities & msi_CapRAudio)) { pthread_mutex_unlock(av->mutex); rc = TOXAV_ERR_SEND_FRAME_PAYLOAD_TYPE_DISABLED; goto END; } pthread_mutex_lock(call->mutex_audio); pthread_mutex_unlock(av->mutex); if (pcm == NULL) { pthread_mutex_unlock(call->mutex_audio); rc = TOXAV_ERR_SEND_FRAME_NULL; goto END; } if (channels > 2) { pthread_mutex_unlock(call->mutex_audio); rc = TOXAV_ERR_SEND_FRAME_INVALID; goto END; } LOGGER_DEBUG("Initial checking took: %llu", current_time_monotonic() - delta); delta = current_time_monotonic(); { /* Encode and send */ if (ac_reconfigure_encoder(call->audio.second, call->audio_bit_rate * 1000, sampling_rate, channels) != 0) { pthread_mutex_unlock(call->mutex_audio); rc = TOXAV_ERR_SEND_FRAME_INVALID; goto END; } LOGGER_DEBUG("Encoder configuration took: %llu", current_time_monotonic() - delta); delta = current_time_monotonic(); uint8_t dest[sample_count + sizeof(sampling_rate)]; /* This is more than enough always */ sampling_rate = htonl(sampling_rate); memcpy(dest, &sampling_rate, sizeof(sampling_rate)); int vrc = opus_encode(call->audio.second->encoder, pcm, sample_count, dest + sizeof(sampling_rate), sizeof(dest) - sizeof(sampling_rate)); LOGGER_DEBUG("Encoding took: %llu", current_time_monotonic() - delta); delta = current_time_monotonic(); if (vrc < 0) { LOGGER_WARNING("Failed to encode frame %s", opus_strerror(vrc)); pthread_mutex_unlock(call->mutex_audio); rc = TOXAV_ERR_SEND_FRAME_INVALID; goto END; } if (rtp_send_data(call->audio.first, dest, vrc + sizeof(sampling_rate)) != 0) { LOGGER_WARNING("Failed to send audio packet"); rc = TOXAV_ERR_SEND_FRAME_RTP_FAILED; } LOGGER_DEBUG("Sending took: %llu", current_time_monotonic() - delta); } pthread_mutex_unlock(call->mutex_audio); END: LOGGER_DEBUG ("End time: %llu Total: %llu", current_time_monotonic(), current_time_monotonic() - start_time); if (error) *error = rc; return rc == TOXAV_ERR_SEND_FRAME_OK; }
bool toxav_video_send_frame(ToxAV *av, uint32_t friend_number, uint16_t width, uint16_t height, const uint8_t *y, const uint8_t *u, const uint8_t *v, TOXAV_ERR_SEND_FRAME *error) { TOXAV_ERR_SEND_FRAME rc = TOXAV_ERR_SEND_FRAME_OK; ToxAVCall *call; if (m_friend_exists(av->m, friend_number) == 0) { rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND; goto END; } if (pthread_mutex_trylock(av->mutex) != 0) { rc = TOXAV_ERR_SEND_FRAME_SYNC; goto END; } call = call_get(av, friend_number); if (call == NULL || !call->active || call->msi_call->state != msi_CallActive) { pthread_mutex_unlock(av->mutex); rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL; goto END; } if (call->video_bit_rate == 0 || !(call->msi_call->self_capabilities & msi_CapSVideo) || !(call->msi_call->peer_capabilities & msi_CapRVideo)) { pthread_mutex_unlock(av->mutex); rc = TOXAV_ERR_SEND_FRAME_PAYLOAD_TYPE_DISABLED; goto END; } pthread_mutex_lock(call->mutex_video); pthread_mutex_unlock(av->mutex); if (y == NULL || u == NULL || v == NULL) { pthread_mutex_unlock(call->mutex_video); rc = TOXAV_ERR_SEND_FRAME_NULL; goto END; } if (vc_reconfigure_encoder(call->video.second, call->video_bit_rate * 1000, width, height) != 0) { pthread_mutex_unlock(call->mutex_video); rc = TOXAV_ERR_SEND_FRAME_INVALID; goto END; } { /* Encode */ vpx_image_t img; img.w = img.h = img.d_w = img.d_h = 0; vpx_img_alloc(&img, VPX_IMG_FMT_I420, width, height, 0); /* I420 "It comprises an NxM Y plane followed by (N/2)x(M/2) V and U planes." * http://fourcc.org/yuv.php#IYUV */ memcpy(img.planes[VPX_PLANE_Y], y, width * height); memcpy(img.planes[VPX_PLANE_U], u, (width / 2) * (height / 2)); memcpy(img.planes[VPX_PLANE_V], v, (width / 2) * (height / 2)); int vrc = vpx_codec_encode(call->video.second->encoder, &img, call->video.second->frame_counter, 1, 0, MAX_ENCODE_TIME_US); vpx_img_free(&img); if (vrc != VPX_CODEC_OK) { pthread_mutex_unlock(call->mutex_video); LOGGER_ERROR("Could not encode video frame: %s\n", vpx_codec_err_to_string(vrc)); rc = TOXAV_ERR_SEND_FRAME_INVALID; goto END; } } ++call->video.second->frame_counter; { /* Send frames */ vpx_codec_iter_t iter = NULL; const vpx_codec_cx_pkt_t *pkt; while ((pkt = vpx_codec_get_cx_data(call->video.second->encoder, &iter))) { if (pkt->kind == VPX_CODEC_CX_FRAME_PKT && rtp_send_data(call->video.first, pkt->data.frame.buf, pkt->data.frame.sz) < 0) { pthread_mutex_unlock(call->mutex_video); LOGGER_WARNING("Could not send video frame: %s\n", strerror(errno)); rc = TOXAV_ERR_SEND_FRAME_RTP_FAILED; goto END; } } } pthread_mutex_unlock(call->mutex_video); END: if (error) *error = rc; return rc == TOXAV_ERR_SEND_FRAME_OK; }
static int handle_connection(RTSPContext *c) { if (c->poll_entry == NULL) { //printf("c -> poll entry is null!! \n"); return 0; } int len, ret; switch(c->state) { case HTTPSTATE_READY: //printf("http state ready \n"); break; case RTSPSTATE_WAIT_REQUEST: /* timeout ? */ if ((c->timeout - cur_time) < 0) return -1; if (c->poll_entry->revents & (POLLERR | POLLHUP)) return -1; /* no need to read if no events */ if (!(c->poll_entry->revents & POLLIN)) return 0; /* read the data */ read_loop: len = recv(c->fd, c->buffer_ptr, 1, 0); if (len < 0) { printf("recv error\n"); return -1; } else if (len == 0) { return -1; } else { /* search for end of request. */ uint8_t *ptr; c->buffer_ptr += len; ptr = c->buffer_ptr; if ((ptr >= c->buffer + 2 && !memcmp(ptr-2, "\n\n", 2)) || (ptr >= c->buffer + 4 && !memcmp(ptr-4, "\r\n\r\n", 4))) { /* request found : parse it and reply */ ret = rtsp_parse_request(c); if (ret < 0) return -1; } else if (ptr >= c->buffer_end) { /* request too long: cannot do anything */ printf("request too long!! \n"); return -1; } else goto read_loop; } break; case RTPSTATE_SEND_DATA: /* for packetized output, we consider we can always write (the input streams set the speed). It may be better to verify that we do not rely too much on the kernel queues */ if (c->poll_entry->revents & (POLLERR | POLLHUP)) return -1; /* no need to read if no events */ if (!(c->poll_entry->revents & POLLOUT)) return 0; if (rtp_send_data(c) < 0) return -1; break; case RTSPSTATE_SEND_REPLY: //printf("rtspstate send reply \n"); if (c->poll_entry->revents & (POLLERR | POLLHUP)) goto close_connection; /* no need to write if no events */ if (!(c->poll_entry->revents & POLLOUT)) return 0; printf("send! reply \n"); len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0); if (len < 0) { printf("send error TT! \n"); goto close_connection; } else { printf("send reply success!! len = %d \n", len); c->buffer_ptr += len; if (c->buffer_ptr >= c->buffer_end) { /* all the buffer was sent : wait for a new request */ av_freep(&c->pb_buffer); start_wait_request(c); } } break; case RTSPSTATE_SEND_PACKET: printf("rtsp send packet! \n"); if (c->poll_entry->revents & (POLLERR | POLLHUP)) { av_freep(&c->pb_buffer); return -1; } /* no need to write if no events */ if (!(c->poll_entry->revents & POLLOUT)) return 0; len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0); if (len < 0) { /* error : close connection */ av_freep(&c->pb_buffer); return -1; } else { c->buffer_ptr += len; if (c->buffer_ptr >= c->buffer_end) { // all the buffer was sent : wait for a new request av_freep(&c->buffer); c->state = RTSPSTATE_WAIT_REQUEST; } } break; default: return -1; } return 0; close_connection: printf("close connection!\n"); av_freep(&c->pb_buffer); return -1; }