input.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:6k
源码类别:

midi

开发平台:

Unix_Linux

  1. /**
  2.  * @file input.c
  3.  * @brief RTP packet input
  4.  */
  5. /*****************************************************************************
  6.  * Copyright © 2008 Rémi Denis-Courmont
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU General Public License
  10.  * as published by the Free Software Foundation; either version 2.0
  11.  * of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Lesser General Public
  19.  * License along with this library; if not, write to the Free Software
  20.  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  21.  ****************************************************************************/
  22. #ifdef HAVE_CONFIG_H
  23. # include <config.h>
  24. #endif
  25. #include <vlc_common.h>
  26. #include <vlc_demux.h>
  27. #include <vlc_block.h>
  28. #include <vlc_network.h>
  29. #include <unistd.h>
  30. #ifdef HAVE_POLL
  31. # include <poll.h>
  32. #endif
  33. #include "rtp.h"
  34. #include <srtp.h>
  35. static bool fd_dead (int fd)
  36. {
  37.     struct pollfd ufd = { .fd = fd, };
  38.     return (poll (&ufd, 1, 0) > 0) && (ufd.revents & POLLHUP);
  39. }
  40. /**
  41.  * Gets a datagram from the network.
  42.  * @param fd datagram file descriptor
  43.  * @return a block or NULL on fatal error (socket dead)
  44.  */
  45. static block_t *rtp_dgram_recv (vlc_object_t *obj, int fd)
  46. {
  47.     block_t *block = block_Alloc (0xffff);
  48.     ssize_t len;
  49.     block_cleanup_push (block);
  50.     do
  51.     {
  52.         len = net_Read (obj, fd, NULL,
  53.                         block->p_buffer, block->i_buffer, false);
  54.         if (((len <= 0) && fd_dead (fd)) || !vlc_object_alive (obj))
  55.         {   /* POLLHUP -> permanent (DCCP) socket error */
  56.             block_Release (block);
  57.             block = NULL;
  58.             break;
  59.         }
  60.     }
  61.     while (len == -1);
  62.     vlc_cleanup_pop ();
  63.     return block ? block_Realloc (block, 0, len) : NULL;
  64. }
  65. /**
  66.  * Gets a framed RTP packet.
  67.  * @param fd stream file descriptor
  68.  * @return a block or NULL in case of fatal error
  69.  */
  70. static block_t *rtp_stream_recv (vlc_object_t *obj, int fd)
  71. {
  72.     ssize_t len = 0;
  73.     uint8_t hdr[2]; /* frame header */
  74.     /* Receives the RTP frame header */
  75.     do
  76.     {
  77.         ssize_t val = net_Read (obj, fd, NULL, hdr + len, 2 - len, false);
  78.         if (val <= 0)
  79.             return NULL;
  80.         len += val;
  81.     }
  82.     while (len < 2);
  83.     block_t *block = block_Alloc (GetWBE (hdr));
  84.     /* Receives the RTP packet */
  85.     for (ssize_t i = 0; i < len;)
  86.     {
  87.         ssize_t val;
  88.         block_cleanup_push (block);
  89.         val = net_Read (obj, fd, NULL,
  90.                         block->p_buffer + i, block->i_buffer - i, false);
  91.         vlc_cleanup_pop ();
  92.         if (val <= 0)
  93.         {
  94.             block_Release (block);
  95.             return NULL;
  96.         }
  97.         i += val;
  98.     }
  99.     return block;
  100. }
  101. static block_t *rtp_recv (demux_t *demux)
  102. {
  103.     demux_sys_t *p_sys = demux->p_sys;
  104.     for (block_t *block;; block_Release (block))
  105.     {
  106.         block = p_sys->framed_rtp
  107.                 ? rtp_stream_recv (VLC_OBJECT (demux), p_sys->fd)
  108.                 : rtp_dgram_recv (VLC_OBJECT (demux), p_sys->fd);
  109.         if (block == NULL)
  110.         {
  111.             msg_Err (demux, "RTP flow stopped");
  112.             break; /* fatal error */
  113.         }
  114.         if (block->i_buffer < 2)
  115.             continue;
  116.         /* FIXME */
  117.         const uint8_t ptype = rtp_ptype (block);
  118.         if (ptype >= 72 && ptype <= 76)
  119.             continue; /* Muxed RTCP, ignore for now */
  120.         if (p_sys->srtp)
  121.         {
  122.             size_t len = block->i_buffer;
  123.             int canc, err;
  124.             canc = vlc_savecancel ();
  125.             err = srtp_recv (p_sys->srtp, block->p_buffer, &len);
  126.             vlc_restorecancel (canc);
  127.             if (err)
  128.             {
  129.                 msg_Dbg (demux, "SRTP authentication/decryption failed");
  130.                 continue;
  131.             }
  132.             block->i_buffer = len;
  133.         }
  134.         return block; /* success! */
  135.     }
  136.     return NULL;
  137. }
  138. void *rtp_thread (void *data)
  139. {
  140.     demux_t *demux = data;
  141.     demux_sys_t *p_sys = demux->p_sys;
  142.     bool autodetect = true;
  143.     do
  144.     {
  145.         block_t *block = rtp_recv (demux);
  146.         int canc = vlc_savecancel ();
  147.         vlc_mutex_lock (&p_sys->lock);
  148.         if (block == NULL)
  149.             p_sys->dead = true; /* Fatal error: abort */
  150.         else
  151.         {
  152.             if (autodetect)
  153.             {   /* Autodetect payload type, _before_ rtp_queue() */
  154.                 if (rtp_autodetect (demux, p_sys->session, block))
  155.                 {
  156.                     vlc_mutex_unlock (&p_sys->lock);
  157.                     block_Release (block);
  158.                     continue;
  159.                 }
  160.                 autodetect = false;
  161.             }
  162.             rtp_queue (demux, p_sys->session, block);
  163.         }
  164.         vlc_cond_signal (&p_sys->wait);
  165.         vlc_mutex_unlock (&p_sys->lock);
  166.         vlc_restorecancel (canc);
  167.     }
  168.     while (!p_sys->dead);
  169.     return NULL;
  170. }
  171. /**
  172.  * Process one RTP packet from the de-jitter queue.
  173.  * @return 0 on success, -1 on EOF
  174.  */
  175. int rtp_process (demux_t *demux)
  176. {
  177.     demux_sys_t *p_sys = demux->p_sys;
  178.     mtime_t deadline = INT64_MAX;
  179.     int ret;
  180.     vlc_mutex_lock (&p_sys->lock);
  181.     if (rtp_dequeue (demux, p_sys->session, &deadline))
  182.         /* Pace the demux thread */
  183.         vlc_cond_timedwait (&p_sys->wait, &p_sys->lock, deadline);
  184.     else
  185.         vlc_cond_wait (&p_sys->wait, &p_sys->lock);
  186.     ret = p_sys->dead ? -1 : 0;
  187.     vlc_mutex_unlock (&p_sys->lock);
  188.     return ret;
  189. }