rtp.c
上传用户:hjq518
上传日期:2021-12-09
资源大小:5084k
文件大小:12k
源码类别:

Audio

开发平台:

Visual C++

  1. /*!
  2.  ************************************************************************
  3.  * file  rtp.c
  4.  *
  5.  * brief
  6.  *    Network Adaptation layer for RTP packets
  7.  *
  8.  * author
  9.  *    Main contributors (see contributors.h for copyright, address and affiliation details)
  10.  *    - Stephan Wenger   <stewe@cs.tu-berlin.de>
  11.  ************************************************************************
  12.  */
  13. /*!
  14.   A quick guide to the basics of the RTP decoder implementation
  15.   This module contains the RTP packetization, de-packetization, and the
  16.   handling of Parameter Sets, see VCEG-N52 and accompanying documents.
  17.   Note: Compound packets are not yet implemented!
  18.   The interface between every NAL (including the RTP NAL) and the VCL is
  19.   based on Slices.  The slice data structure on which the VCL is working
  20.   is defined in the type Slice (in defines.h).  This type contains the
  21.   various fields of the slice header and a partition array, which itself
  22.   contains the data partitions the slice consists of.  When data
  23.   partitioning is not used, then the whole slice bit string is stored
  24.   in partition #0.  When individual partitions are missing, this is
  25.   indicated by the size of the bit strings in the partition array.
  26.   A complete missing slice (e.g. if a Full Slice packet was lost) is
  27.   indicated in a similar way.
  28.   part of the slice structure is the error indication (ei-flag).  The
  29.   Ei-flag is set in such cases in which at least one partition of a slice
  30.   is damaged or missing.When data partitioning is used, it can happen that
  31.   one partition does not contain any symbols but the ei_flag is cleared,
  32.   which indicates the intentional missing of symbols of that partition.
  33.   A typical example for this behaviour is the Intra Slice, which does not
  34.   have symnbols in its type C partition.
  35.   The VCL requests new data to work on through the call of readSliceRTP().
  36.   This function calls the main state machine of this module in ReadRTPpaacket().
  37.   ReadRTPpacket assumes, when called, that in an error free environment
  38.   a complete slice, consisting of one Full Slice RTP packet, or three Partition
  39.   packets of types A, B, C with consecutive sequence numbers, can be read.
  40.   It first interprets any trailing SUPP and Parameter Update (Header) packets.
  41.   Then it reads one video data packet.  Two cases have to be distinguished:
  42.   1. Type A, or Full Slice packet
  43.   In this case, the PictureID and the macroblock mumbers are used to
  44.   identify the potential loss of a slice.  A slice is lost, when the
  45.   StartMB of the newly read slice header is not equal to the current
  46.   state of the decoder
  47.     1.1 Loss detected
  48.       In this case the last packet is unread (fseek back), and a dummy slice
  49.       containing the missing macroblocks is conveyed to the VCL.  At the next
  50.       call of the NAL, the same packet is read again, but this time no packet
  51.       loss is detected by the above algorithm,
  52.     1.2. No loss
  53.       In this case it is checked whether a Full Slice packet or a type A data
  54.       partition was read
  55.         1.2.1 Full Slice
  56.           The Full Slice packet is conveyed to the NAL
  57.         1.2.2 Type A Partition
  58.           The function RTPReadDataPartitionedSlice() is called, which collects
  59.           the remaining type B, C partitions and handles them appropriately.
  60.   Paraneter Update Packets (aka Header packets) are in an SDP-like syntax
  61.   and are interpreted by a simple parser in the function
  62.   RTPInterpretParameterSetPacket()
  63.   Each Slice header contaions the information on which parameter set to be used.
  64.   The function RTPSetImgInp() copies the information of the relevant parameter
  65.   set in the VCL's global variables img-> and inp->  IMPORTANT: any changes
  66.   in the semantics of the img-> and inp-> structure members must be represented
  67.   in this function as well!
  68.   A note to the stream-buffer data structure: The stream buffer always contains
  69.   only the contents of the partition in question, and not the slice/partition
  70.   header.  Decoding has to start at bitoffset 0 (UVLC) or bytreoffset 0 (CABAC).
  71.   The remaining functions should be self-explanatory.
  72. */
  73. #ifdef WIN32
  74. #include <Winsock2.h>
  75. #else
  76. #include <netinet/in.h>
  77. #endif
  78. #include "contributors.h"
  79. #include "global.h"
  80. #include "errorconcealment.h"
  81. #include "rtp.h"
  82. #include "fmo.h"
  83. #include "sei.h"
  84. #include "memalloc.h"
  85. FILE *bits;
  86. int RTPReadPacket (RTPpacket_t *p, FILE *bitstream);
  87. /*!
  88.  ************************************************************************
  89.  * brief
  90.  *    Opens the bit stream file named fn
  91.  * return
  92.  *    none
  93.  ************************************************************************
  94.  */
  95. void OpenRTPFile (char *fn)
  96. {
  97.   if (NULL == (bits=fopen(fn, "rb")))
  98.   {
  99.     snprintf (errortext, ET_SIZE, "Cannot open RTP file '%s'", params->infile);
  100.     error(errortext,500);
  101.   }
  102. }
  103. /*!
  104.  ************************************************************************
  105.  * brief
  106.  *    Closes the bit stream file
  107.  ************************************************************************
  108.  */
  109. void CloseRTPFile(void)
  110. {
  111.   fclose (bits);
  112. }
  113. /*!
  114.  ************************************************************************
  115.  * brief
  116.  *    Fills nalu->buf and nalu->len with the payload of an RTP packet.
  117.  *    Other fields in nalu-> remain uninitialized (will be taken care of
  118.  *    by NALUtoRBSP.
  119.  *
  120.  * return
  121.  *     4 in case of ok (for compatibility with GetAnnexbNALU)
  122.  *     0 if there is nothing any more to read (EOF)
  123.  *    -1 in case of any error
  124.  *
  125.  ************************************************************************
  126.  */
  127. int GetRTPNALU (FILE *bitstream, NALU_t *nalu)
  128. {
  129.   static unsigned short first_call = 1;  //!< triggers sequence number initialization on first call
  130.   static unsigned short old_seq = 0;     //!< store the last RTP sequence number for loss detection
  131.   RTPpacket_t *p;
  132.   int ret;
  133.   if ((p=malloc (sizeof (RTPpacket_t)))== NULL)
  134.     no_mem_exit ("GetRTPNALU-1");
  135.   if ((p->packet=malloc (MAXRTPPACKETSIZE))== NULL)
  136.     no_mem_exit ("GetRTPNALU-2");
  137.   if ((p->payload=malloc (MAXRTPPACKETSIZE))== NULL)
  138.     no_mem_exit ("GetRTPNALU-3");
  139.   ret = RTPReadPacket (p, bitstream);
  140.   nalu->forbidden_bit = 1;
  141.   nalu->len = 0;
  142.   if (ret > 0) // we got a packet ( -1=error, 0=end of file )
  143.   {
  144.     if (first_call)
  145.     {
  146.       first_call = 0;
  147.       old_seq = (unsigned short) (p->seq - 1);
  148.     }
  149.     nalu->lost_packets = (unsigned short) ( p->seq - (old_seq + 1) );
  150.     old_seq = p->seq;
  151.     assert (p->paylen < nalu->max_size);
  152.     nalu->len = p->paylen;
  153.     memcpy (nalu->buf, p->payload, p->paylen);
  154.     nalu->forbidden_bit = (nalu->buf[0]>>7) & 1;
  155.     nalu->nal_reference_idc = (nalu->buf[0]>>5) & 3;
  156.     nalu->nal_unit_type = (nalu->buf[0]) & 0x1f;
  157.     if (nalu->lost_packets)
  158.     {
  159.       printf ("Warning: RTP sequence number discontinuity detectedn");
  160.     }
  161.   }
  162.   // free memory
  163.   free (p->payload);
  164.   free (p->packet);
  165.   free (p);
  166. //  printf ("Got an RTP NALU, len %d, first byte %xn", nalu->len, nalu->buf[0]);
  167.   
  168.   if (ret>0)
  169.     // length of packet
  170.     return nalu->len;
  171.   else 
  172.     // error code
  173.     return ret;
  174. }
  175. /*!
  176.  *****************************************************************************
  177.  *
  178.  * brief
  179.  *    DecomposeRTPpacket interprets the RTP packet and writes the various
  180.  *    structure members of the RTPpacket_t structure
  181.  *
  182.  * return
  183.  *    0 in case of success
  184.  *    negative error code in case of failure
  185.  *
  186.  * param p
  187.  *    Caller is responsible to allocate enough memory for the generated payload
  188.  *    in parameter->payload. Typically a malloc of paclen-12 bytes is sufficient
  189.  *
  190.  * par Side effects
  191.  *    none
  192.  *
  193.  * date
  194.  *    30 Spetember 2001
  195.  *
  196.  * author
  197.  *    Stephan Wenger   stewe@cs.tu-berlin.de
  198.  *****************************************************************************/
  199. int DecomposeRTPpacket (RTPpacket_t *p)
  200. {
  201.   // consistency check
  202.   assert (p->packlen < 65536 - 28);  // IP, UDP headers
  203.   assert (p->packlen >= 12);         // at least a complete RTP header
  204.   assert (p->payload != NULL);
  205.   assert (p->packet != NULL);
  206.   // Extract header information
  207.   p->v  = (p->packet[0] >> 6) & 0x03;
  208.   p->p  = (p->packet[0] >> 5) & 0x01;
  209.   p->x  = (p->packet[0] >> 4) & 0x01;
  210.   p->cc = (p->packet[0] >> 0) & 0x0F;
  211.   p->m  = (p->packet[1] >> 7) & 0x01;
  212.   p->pt = (p->packet[1] >> 0) & 0x7F;
  213.   memcpy (&p->seq, &p->packet[2], 2);
  214.   p->seq = ntohs((unsigned short)p->seq);
  215.   memcpy (&p->timestamp, &p->packet[4], 4);// change to shifts for unified byte sex
  216.   p->timestamp = ntohl(p->timestamp);
  217.   memcpy (&p->ssrc, &p->packet[8], 4);// change to shifts for unified byte sex
  218.   p->ssrc = ntohl(p->ssrc);
  219.   // header consistency checks
  220.   if (     (p->v != 2)
  221.         || (p->p != 0)
  222.         || (p->x != 0)
  223.         || (p->cc != 0) )
  224.   {
  225.     printf ("DecomposeRTPpacket, RTP header consistency problem, header followsn");
  226.     DumpRTPHeader (p);
  227.     return -1;
  228.   }
  229.   p->paylen = p->packlen-12;
  230.   memcpy (p->payload, &p->packet[12], p->paylen);
  231.   return 0;
  232. }
  233. /*!
  234.  *****************************************************************************
  235.  *
  236.  * brief
  237.  *    DumpRTPHeader is a debug tool that dumps a human-readable interpretation
  238.  *    of the RTP header
  239.  *
  240.  * return
  241.  *    n.a.
  242.  * param p
  243.  *    the RTP packet to be dumped, after DecompositeRTPpacket()
  244.  *
  245.  * par Side effects
  246.  *    Debug output to stdout
  247.  *
  248.  * date
  249.  *    30 Spetember 2001
  250.  *
  251.  * author
  252.  *    Stephan Wenger   stewe@cs.tu-berlin.de
  253.  *****************************************************************************/
  254. void DumpRTPHeader (RTPpacket_t *p)
  255. {
  256.   int i;
  257.   for (i=0; i< 30; i++)
  258.     printf ("%02x ", p->packet[i]);
  259.   printf ("Version (V): %dn", (int) p->v);
  260.   printf ("Padding (P): %dn", (int) p->p);
  261.   printf ("Extension (X): %dn", (int) p->x);
  262.   printf ("CSRC count (CC): %dn", (int) p->cc);
  263.   printf ("Marker bit (M): %dn", (int) p->m);
  264.   printf ("Payload Type (PT): %dn", (int) p->pt);
  265.   printf ("Sequence Number: %dn", (int) p->seq);
  266.   printf ("Timestamp: %dn", (int) p->timestamp);
  267.   printf ("SSRC: %dn", (int) p->ssrc);
  268. }
  269. /*!
  270.  *****************************************************************************
  271.  *
  272.  * brief
  273.  *    RTPReadPacket reads one packet from file
  274.  *
  275.  * return
  276.  *    0: EOF
  277.  *    negative: error
  278.  *    positive: size of RTP packet in bytes
  279.  *
  280.  * param p
  281.  *    packet data structure, with memory for p->packet allocated
  282.  *
  283.  * param bits
  284.  *    target file
  285.  *
  286.  * par Side effects:
  287.  *   - File pointer in bits moved
  288.  *   - p->xxx filled by reading and Decomposepacket()
  289.  *
  290.  * date
  291.  *    04 November, 2001
  292.  *
  293.  * author
  294.  *    Stephan Wenger, stewe@cs.tu-berlin.de
  295.  *****************************************************************************/
  296. int RTPReadPacket (RTPpacket_t *p, FILE *bitstream)
  297. {
  298.   int Filepos, intime;
  299.   assert (p != NULL);
  300.   assert (p->packet != NULL);
  301.   assert (p->payload != NULL);
  302.   Filepos = ftell (bitstream);
  303.   if (4 != fread (&p->packlen,1, 4, bitstream))
  304.   {
  305.     return 0;
  306.   }
  307.   if (4 != fread (&intime, 1, 4, bitstream))
  308.   {
  309.     fseek (bitstream, Filepos, SEEK_SET);
  310.     printf ("RTPReadPacket: File corruption, could not read Timestamp, exitn");
  311.     exit (-1);
  312.   }
  313.   assert (p->packlen < MAXRTPPACKETSIZE);
  314.   if (p->packlen != fread (p->packet, 1, p->packlen, bitstream))
  315.   {
  316.     printf ("RTPReadPacket: File corruption, could not read %d bytesn", (int) p->packlen);
  317.     exit (-1);    // EOF inidication
  318.   }
  319.   if (DecomposeRTPpacket (p) < 0)
  320.   {
  321.     // this should never happen, hence exit() is ok.  We probably do not want to attempt
  322.     // to decode a packet that obviously wasn't generated by RTP
  323.     printf ("Errors reported by DecomposePacket(), exitn");
  324.     exit (-700);
  325.   }
  326.   assert (p->pt == H264PAYLOADTYPE);
  327.   assert (p->ssrc == H264SSRC);
  328.   return p->packlen;
  329. }