/** * Process one RTP packet from the de-jitter queue. */ static void rtp_process (void *data) { demux_t *demux = data; demux_sys_t *p_sys = demux->p_sys; mtime_t deadline; vlc_mutex_lock (&p_sys->lock); if (rtp_dequeue (demux, p_sys->session, &deadline)) vlc_timer_schedule (p_sys->timer, true, deadline, 0); vlc_mutex_unlock (&p_sys->lock); }
/** * RTP/RTCP session thread for datagram sockets */ void *rtp_dgram_thread (void *opaque) { demux_t *demux = opaque; demux_sys_t *sys = demux->p_sys; mtime_t deadline = VLC_TS_INVALID; int rtp_fd = sys->fd; struct pollfd ufd[1]; ufd[0].fd = rtp_fd; ufd[0].events = POLLIN; for (;;) { int n = poll (ufd, 1, rtp_timeout (deadline)); if (n == -1) continue; int canc = vlc_savecancel (); if (n == 0) goto dequeue; if (ufd[0].revents) { n--; if (unlikely(ufd[0].revents & POLLHUP)) break; /* RTP socket dead (DCCP only) */ block_t *block = block_Alloc (0xffff); /* TODO: p_sys->mru */ if (unlikely(block == NULL)) break; /* we are totallly screwed */ ssize_t len = recv (rtp_fd, block->p_buffer, block->i_buffer, 0); if (len != -1) { block->i_buffer = len; rtp_process (demux, block); } else { msg_Warn (demux, "RTP network error: %m"); block_Release (block); } } dequeue: if (!rtp_dequeue (demux, sys->session, &deadline)) deadline = VLC_TS_INVALID; vlc_restorecancel (canc); } return NULL; }
/** * RTP/RTCP session thread for datagram sockets */ void *rtp_dgram_thread (void *opaque) { demux_t *demux = opaque; demux_sys_t *sys = demux->p_sys; mtime_t deadline = VLC_TS_INVALID; int rtp_fd = sys->fd; struct iovec iov = { .iov_len = DEFAULT_MRU, }; struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1, }; struct pollfd ufd[1]; ufd[0].fd = rtp_fd; ufd[0].events = POLLIN; for (;;) { int n = poll (ufd, 1, rtp_timeout (deadline)); if (n == -1) continue; int canc = vlc_savecancel (); if (n == 0) goto dequeue; if (ufd[0].revents) { n--; if (unlikely(ufd[0].revents & POLLHUP)) break; /* RTP socket dead (DCCP only) */ block_t *block = block_Alloc (iov.iov_len); if (unlikely(block == NULL)) { if (iov.iov_len == DEFAULT_MRU) break; /* we are totallly screwed */ iov.iov_len = DEFAULT_MRU; continue; /* retry with shrunk MRU */ } iov.iov_base = block->p_buffer; #ifdef __linux__ msg.msg_flags = MSG_TRUNC; #else msg.msg_flags = 0; #endif ssize_t len = recvmsg (rtp_fd, &msg, 0); if (len != -1) { #ifdef MSG_TRUNC if (msg.msg_flags & MSG_TRUNC) { msg_Err(demux, "%zd bytes packet truncated (MRU was %zu)", len, iov.iov_len); block->i_flags |= BLOCK_FLAG_CORRUPTED; iov.iov_len = len; } else #endif block->i_buffer = len; rtp_process (demux, block); } else { msg_Warn (demux, "RTP network error: %s", vlc_strerror_c(errno)); block_Release (block); } } dequeue: if (!rtp_dequeue (demux, sys->session, &deadline)) deadline = VLC_TS_INVALID; vlc_restorecancel (canc); } return NULL; } /** * RTP/RTCP session thread for stream sockets (framed RTP) */ void *rtp_stream_thread (void *opaque) { #ifndef _WIN32 demux_t *demux = opaque; demux_sys_t *sys = demux->p_sys; int fd = sys->fd; for (;;) { /* There is no reordering on stream sockets, so no timeout. */ ssize_t val; uint16_t frame_len; if (recv (fd, &frame_len, 2, MSG_WAITALL) != 2) break; block_t *block = block_Alloc (ntohs (frame_len)); if (unlikely(block == NULL)) break; block_cleanup_push (block); val = recv (fd, block->p_buffer, block->i_buffer, MSG_WAITALL); vlc_cleanup_pop (); if (val != (ssize_t)block->i_buffer) { block_Release (block); break; } int canc = vlc_savecancel (); rtp_process (demux, block); rtp_dequeue_force (demux, sys->session); vlc_restorecancel (canc); } #else (void) opaque; #endif return NULL; }