int main() { tlog_init(TLOG_MODE_STDERR, TLOG_INFO, NULL); rcp_connect("10.25.25.220"); start_message_manager(); client_register(RCP_USER_LEVEL_LIVE, "", RCP_REGISTRATION_TYPE_NORMAL, RCP_ENCRYPTION_MODE_MD5); rcp_coder_list encoders, decoders; get_coder_list(RCP_CODER_ENCODER, RCP_MEDIA_TYPE_VIDEO, &encoders, 1); TL_DEBUG("***"); for (int i=0; i<encoders.count; i++) TL_DEBUG("%x %x %x %x %x", encoders.coder[i].number, encoders.coder[i].caps, encoders.coder[i].current_cap, encoders.coder[i].param_caps, encoders.coder[i].current_param); TL_DEBUG("***"); get_coder_list(RCP_CODER_DECODER, RCP_MEDIA_TYPE_VIDEO, &decoders, 1); TL_DEBUG("***"); for (int i=0; i<decoders.count; i++) TL_DEBUG("%x %x %x %x %x", decoders.coder[i].number, decoders.coder[i].caps, decoders.coder[i].current_cap, decoders.coder[i].param_caps, decoders.coder[i].current_param); TL_DEBUG("***"); rcp_session session; memset(&session, 0, sizeof(rcp_session)); unsigned short udp_port = stream_connect_udp(&session); TL_DEBUG("udp port = %d", udp_port); rcp_media_descriptor desc = { RCP_MEP_UDP, 1, 1, 0, udp_port, 0, 1, RCP_VIDEO_CODING_MPEG4, RCP_VIDEO_RESOLUTION_4CIF }; client_connect(&session, RCP_CONNECTION_METHOD_GET, RCP_MEDIA_TYPE_VIDEO, 0, &desc); pthread_create(&thread, NULL, keep_alive_thread, &session); rtp_merge_desc mdesc; rtp_init(RTP_PAYLOAD_TYPE_H263, 1, &mdesc); time_t end_time = time(NULL) + 10; while (time(NULL) < end_time) { /* int num = recvfrom(con.stream_socket, buffer, 1500, 0, (struct sockaddr*)&si_remote, &slen); rtp_push_frame(buffer, num, &mdesc); */ rtp_recv(session.stream_socket, &mdesc); if (rtp_pop_frame(&mdesc) == 0) fwrite(mdesc.data, mdesc.frame_lenght, 1, stdout); } pthread_cancel(thread); stop_message_manager(); return 0; }
INT16 rtp_version_recv(RTP *rtp) { UINT16 type; INT32 zero = 0; if (!rtp_recv(rtp, (UINT8 *) NULL, &type, &zero)) return (INT16) -1; return (INT16) type; }
void *rtp_thread (void *data) { demux_t *demux = data; demux_sys_t *p_sys = demux->p_sys; bool autodetect = true; if (vlc_timer_create (&p_sys->timer, rtp_process, data)) return NULL; vlc_cleanup_push (timer_cleanup, (void *)p_sys->timer); for (;;) { block_t *block = rtp_recv (demux); if (block == NULL) break; if (autodetect) { /* Autodetect payload type, _before_ rtp_queue() */ /* No need for lock - the queue is empty. */ if (rtp_autodetect (demux, p_sys->session, block)) { block_Release (block); continue; } autodetect = false; } int canc = vlc_savecancel (); vlc_mutex_lock (&p_sys->lock); rtp_queue (demux, p_sys->session, block); vlc_mutex_unlock (&p_sys->lock); vlc_restorecancel (canc); rtp_process (demux); } vlc_cleanup_run (); return NULL; }
int main(int argc, char* argv[]) { tlog_init(TLOG_MODE_STDERR, TLOG_INFO, NULL); if (argc < 3) { TL_INFO("%s <ip> <output>", argv[0]); return 0; } rcp_connect(argv[1]); start_message_manager(); client_register(RCP_USER_LEVEL_LIVE, "", RCP_REGISTRATION_TYPE_NORMAL, RCP_ENCRYPTION_MODE_MD5); rcp_coder_list encoders, decoders; get_coder_list(RCP_CODER_ENCODER, RCP_MEDIA_TYPE_VIDEO, &encoders, 1); TL_DEBUG("***"); for (int i=0; i<encoders.count; i++) TL_DEBUG("%x %x %x %x %x", encoders.coder[i].number, encoders.coder[i].caps, encoders.coder[i].current_cap, encoders.coder[i].param_caps, encoders.coder[i].current_param); TL_DEBUG("***"); get_coder_list(RCP_CODER_DECODER, RCP_MEDIA_TYPE_VIDEO, &decoders, 1); TL_DEBUG("***"); for (int i=0; i<decoders.count; i++) TL_DEBUG("%x %x %x %x %x", decoders.coder[i].number, decoders.coder[i].caps, decoders.coder[i].current_cap, decoders.coder[i].param_caps, decoders.coder[i].current_param); TL_DEBUG("***"); rcp_session session; memset(&session, 0, sizeof(rcp_session)); unsigned short udp_port = stream_connect_udp(&session); TL_DEBUG("udp port = %d", udp_port); rcp_media_descriptor desc = { RCP_MEP_UDP, 1, 1, 0, udp_port, 1, 1, RCP_VIDEO_CODING_H264, RCP_VIDEO_RESOLUTION_4CIF }; client_connect(&session, RCP_CONNECTION_METHOD_GET, RCP_MEDIA_TYPE_VIDEO, 0, &desc); pthread_create(&thread, NULL, keep_alive_thread, &session); rtp_merge_desc mdesc; rtp_init(RTP_PAYLOAD_TYPE_H264, 1, &mdesc); signal(SIGTERM, term_handler); FILE * out = fopen(argv[2], "wb"); while (!end) { /* int num = recvfrom(con.stream_socket, buffer, 1500, 0, (struct sockaddr*)&si_remote, &slen); rtp_push_frame(buffer, num, &mdesc); */ if (rtp_recv(session.stream_socket, &mdesc) == 0) { if (rtp_pop_frame(&mdesc) == 0) { fwrite(mdesc.data, mdesc.frame_lenght, 1, out); } } //char cmd[100]; //sprintf(cmd, "kill %d", res); //system(cmd); //return 0; } fclose(out); pthread_cancel(thread); client_disconnect(&session); client_unregister(); stop_message_manager(); return 0; }
static void rxmit_packets(struct cfg *cf, struct rtpp_session *sp, int ridx, double dtime) { int ndrain, i, port; struct rtp_packet *packet = NULL; /* Repeat since we may have several packets queued on the same socket */ for (ndrain = 0; ndrain < 5; ndrain++) { if (packet != NULL) rtp_packet_free(packet); packet = rtp_recv(sp->fds[ridx]); if (packet == NULL) break; packet->laddr = sp->laddr[ridx]; packet->rport = sp->ports[ridx]; packet->rtime = dtime; i = 0; if (sp->addr[ridx] != NULL) { /* Check that the packet is authentic, drop if it isn't */ if (sp->asymmetric[ridx] == 0) { if (memcmp(sp->addr[ridx], &packet->raddr, packet->rlen) != 0) { if (sp->canupdate[ridx] == 0) { /* * Continue, since there could be good packets in * queue. */ continue; } /* Signal that an address has to be updated */ i = 1; } else if (sp->canupdate[ridx] != 0 && sp->last_update[ridx] != 0 && dtime - sp->last_update[ridx] > UPDATE_WINDOW) { sp->canupdate[ridx] = 0; } } else { /* * For asymmetric clients don't check * source port since it may be different. */ if (!ishostseq(sp->addr[ridx], sstosa(&packet->raddr))) /* * Continue, since there could be good packets in * queue. */ continue; } sp->pcount[ridx]++; } else { sp->pcount[ridx]++; sp->addr[ridx] = malloc(packet->rlen); if (sp->addr[ridx] == NULL) { sp->pcount[3]++; rtpp_log_write(RTPP_LOG_ERR, sp->log, "can't allocate memory for remote address - " "removing session"); remove_session(cf, GET_RTP(sp)); /* Break, sp is invalid now */ break; } /* Signal that an address have to be updated. */ i = 1; } /* * Update recorded address if it's necessary. Set "untrusted address" * flag in the session state, so that possible future address updates * from that client won't get address changed immediately to some * bogus one. */ if (i != 0) { sp->untrusted_addr[ridx] = 1; memcpy(sp->addr[ridx], &packet->raddr, packet->rlen); if (sp->prev_addr[ridx] == NULL || memcmp(sp->prev_addr[ridx], &packet->raddr, packet->rlen) != 0) { sp->canupdate[ridx] = 0; } port = ntohs(satosin(&packet->raddr)->sin_port); rtpp_log_write(RTPP_LOG_INFO, sp->log, "%s's address filled in: %s:%d (%s)", (ridx == 0) ? "callee" : "caller", addr2char(sstosa(&packet->raddr)), port, (sp->rtp == NULL) ? "RTP" : "RTCP"); /* * Check if we have updated RTP while RTCP is still * empty or contains address that differs from one we * used when updating RTP. Try to guess RTCP if so, * should be handy for non-NAT'ed clients, and some * NATed as well. */ if (sp->rtcp != NULL && (sp->rtcp->addr[ridx] == NULL || !ishostseq(sp->rtcp->addr[ridx], sstosa(&packet->raddr)))) { if (sp->rtcp->addr[ridx] == NULL) { sp->rtcp->addr[ridx] = malloc(packet->rlen); if (sp->rtcp->addr[ridx] == NULL) { sp->pcount[3]++; rtpp_log_write(RTPP_LOG_ERR, sp->log, "can't allocate memory for remote address - " "removing session"); remove_session(cf, sp); /* Break, sp is invalid now */ break; } } memcpy(sp->rtcp->addr[ridx], &packet->raddr, packet->rlen); satosin(sp->rtcp->addr[ridx])->sin_port = htons(port + 1); /* Use guessed value as the only true one for asymmetric clients */ sp->rtcp->canupdate[ridx] = NOT(sp->rtcp->asymmetric[ridx]); rtpp_log_write(RTPP_LOG_INFO, sp->log, "guessing RTCP port " "for %s to be %d", (ridx == 0) ? "callee" : "caller", port + 1); } } if (sp->resizers[ridx].output_nsamples > 0) rtp_resizer_enqueue(&sp->resizers[ridx], &packet); if (packet != NULL) send_packet(cf, sp, ridx, packet); } if (packet != NULL) rtp_packet_free(packet); }
void *mod_cin (void *ptr) { int rtpfd; /* RTP socket file descriptor */ int rtcpfd; /* RTCP socket file descriptor */ socklen_t addr_len; /* Data size, Bytes received */ struct sockaddr_in rtps; /* RTP socket */ struct sockaddr_in rtcps; /* RTCP socket */ struct sockaddr_in remote; /* Remote address information */ vstr_t recv_data; /* Received data */ rtp_packet_t *packet; /* Parsed RTP packet */ fd_set readset; int fdmax; fprintf(stderr, "+ Communication input module loaded.\n"); vstr_init (&recv_data, RTP_MTU_SIZE); if ((rtpfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("Error opening socket"); exit(1); } if ((rtcpfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("Error opening socket"); exit(1); } rtps.sin_family = AF_INET; /* Internet protocol */ rtps.sin_port = htons(RTP_PORT); /* Port */ rtps.sin_addr.s_addr = htonl(INADDR_ANY); /* rtps address */ memset(&(rtps.sin_zero), '\0', 8); /* Zero the rest */ if (bind(rtpfd, (struct sockaddr *) &rtps, sizeof(struct sockaddr)) < 0) { perror("Error binding socket"); exit(1); } rtcps.sin_family = AF_INET; /* Internet protocol */ rtcps.sin_port = htons(RTCP_PORT); /* Port */ rtcps.sin_addr.s_addr = htonl(INADDR_ANY); /* rtcps address */ memset(&(rtcps.sin_zero), '\0', 8); /* Zero the rest */ if (bind(rtcpfd, (struct sockaddr *) &rtcps, sizeof(struct sockaddr)) < 0) { perror("Error binding socket"); exit(1); } fprintf(stderr, "+ RTP Listening at %s:%d...\n", inet_ntoa(rtps.sin_addr), ntohs(rtps.sin_port)); fprintf(stderr, "+ RTCP Listening at %s:%d...\n", inet_ntoa(rtcps.sin_addr), ntohs(rtcps.sin_port)); addr_len = sizeof(struct sockaddr); while(1) { FD_ZERO (&readset); FD_SET (rtpfd, &readset); FD_SET (rtcpfd, &readset); fdmax = (rtpfd < rtcpfd) ? rtcpfd : rtpfd; select (fdmax + 1, &readset, NULL, NULL, NULL); if (FD_ISSET(rtpfd, &readset)) { /* Receive data from network */ recv_data.size = recvfrom (rtpfd, recv_data.data, RTP_MTU_SIZE, 0, (struct sockaddr *)&remote, &addr_len); printf("receive data, size = %d!!!!!!!!!!!!!!!!!\n", recv_data.size); vstr_adv_tail (&recv_data, recv_data.size); if (recv_data.size < 0) { perror("Error receiving data from socket"); exit(1); } /* Write to buffer */ packet = rtp_recv (&rtp, &recv_data); if (packet != NULL && rtp_enqueue (&rtp, packet) == -1) rtp_packet_free (packet); vstr_flush (&recv_data); } if (FD_ISSET(rtcpfd, &readset)) { /* Receive data from network */ recv_data.size = recvfrom (rtcpfd, recv_data.data, RTP_MTU_SIZE, 0, (struct sockaddr *)&remote, &addr_len); vstr_adv_tail (&recv_data, recv_data.size); if (recv_data.size < 0) { perror("Error receiving data from socket"); exit(1); } rtcp_recv (&rtp, &recv_data); vstr_flush (&recv_data); } } }
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; }
static BOOL handshake(RTP *rtp) { UINT16 type; INT16 client_version; INT32 unused; struct rtp_attr attr; UINT8 msgbuf[RTP_MAXMSGLEN]; static CHAR *fid = "handshake"; /* Get the client protocol version number */ rtp_log(RTP_DEBUG, "%s: read client protocol version", fid); if ((client_version = rtp_version_recv(rtp)) < 0) { rtp_log(RTP_ERR, "%s: rtp_version_recv: error %d", fid, client_version ); return FALSE; } rtp_log(RTP_DEBUG, "%s: client version is %d", fid, client_version); /* Send back our version number */ rtp_log(RTP_DEBUG, "%s: send server protcol version %d", fid, RTP_VERSION ); if (!rtp_version_send(rtp)) { rtp_log(RTP_ERR, "%s: rtp_version_send failed", fid); return FALSE; } /* If the client is a higher version, protocol says quit now */ if (client_version > RTP_VERSION) { rtp_log(RTP_ERR, "%s: unsupported protocol version (%d)", fid, client_version ); return FALSE; } /* Following is specific to protocol version */ if (client_version == 1) { /* client should begin with its process id */ if (!rtp_recv(rtp, msgbuf, &type, &unused)) { rtp_log(RTP_ERR, "%s: rtp_recv failed", fid); return FALSE; } if (type != RTP_MSG_PID) { rtp_log(RTP_ERR, "%s: unexpected message type %d != %d", fid, type, RTP_MSG_ATTR ); errno = EPROTO; return FALSE; } rtp_pid_decode(msgbuf, &rtp->pid); rtp_log(RTP_DEBUG, "%s: client process id is %d", fid, rtp->pid); /* which we acknowledge with our process id */ rtp_log(RTP_DEBUG, "%s: send pid ack", fid); if (!rtp_pid_send(rtp)) { rtp_log(RTP_ERR, "%s: rtp_pid_send failed", fid); return FALSE; } /* client should then send its attribute request */ if (!rtp_recv(rtp, msgbuf, &type, &unused)) { rtp_log(RTP_ERR, "%s: rtp_recv failed", fid); return FALSE; } if (type != RTP_MSG_ATTR) { rtp_log(RTP_ERR, "%s: unexpected message type %d != %d", fid, type, RTP_MSG_ATTR ); errno = EPROTO; return FALSE; } rtp_attr_decode(msgbuf, &attr); rtp_log(RTP_DEBUG, "%s: client attribute request received", fid); /* which will load in and echo back (maybe change it, too) */ if (!set_attr(rtp, &attr)) { rtp_log(RTP_ERR, "%s: set_attr failed", fid); rtp_break(rtp); return FALSE; } rtp_log(RTP_DEBUG, "%s: send attribute ack", fid); if (!rtp_attr_send(rtp, &attr)) { return FALSE; } } else { rtp_log(RTP_ERR, "%s: unsupported protocol version (%d)", fid, client_version ); errno = EPROTO; rtp_break(rtp); return FALSE; } rtp_log(RTP_DEBUG, "%s: handshake complete", fid); return TRUE; }
/**************************************************************************** * RTP receive routines ****************************************************************************/ int CPlayerMedia::recv_thread (void) { struct timeval timeout; int retcode; CMsg *newmsg; int recv_thread_stop = 0; m_rtp_buffering = 0; if (m_ports != NULL) { /* * We need to free up the ports that we got before RTP tries to set * them up, so we don't have any re-use conflicts. There is a small * window here that they might get used... */ delete m_ports; // free up the port numbers m_ports = NULL; } #ifdef _WIN32 WORD wVersionRequested; WSADATA wsaData; int ret; wVersionRequested = MAKEWORD( 2, 0 ); ret = WSAStartup( wVersionRequested, &wsaData ); if ( ret != 0 ) { abort(); } #endif rtp_init(false); if (m_rtp_session != NULL) { rtp_start(); } while (recv_thread_stop == 0) { if ((newmsg = m_rtp_msg_queue.get_message()) != NULL) { //player_debug_message("recv thread message %d", newmsg->get_value()); switch (newmsg->get_value()) { case MSG_STOP_THREAD: recv_thread_stop = 1; break; case MSG_PAUSE_SESSION: // Indicate that we need to restart the session. // But keep going... rtp_start(); break; } delete newmsg; newmsg = NULL; } if (recv_thread_stop == 1) { continue; } if (m_rtp_session == NULL) { SDL_Delay(50); } else { if (m_rtp_session_from_outside) { SDL_Delay(500); } else { timeout.tv_sec = 0; timeout.tv_usec = 500000; retcode = rtp_recv(m_rtp_session, &timeout, 0); } // player_debug_message("rtp_recv return %d", retcode); // Run rtp periodic after each packet received or idle time. if (m_paused == false || m_stream_ondemand != 0) rtp_periodic(); } } /* * When we're done, send a bye, close up rtp, and go home */ rtp_end(); return (0); }