rtp.c
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:17k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*
  2. ***********************************************************************
  3. * COPYRIGHT AND WARRANTY INFORMATION
  4. *
  5. * Copyright 2001, International Telecommunications Union, Geneva
  6. *
  7. * DISCLAIMER OF WARRANTY
  8. *
  9. * These software programs are available to the user without any
  10. * license fee or royalty on an "as is" basis. The ITU disclaims
  11. * any and all warranties, whether express, implied, or
  12. * statutory, including any implied warranties of merchantability
  13. * or of fitness for a particular purpose.  In no event shall the
  14. * contributor or the ITU be liable for any incidental, punitive, or
  15. * consequential damages of any kind whatsoever arising from the
  16. * use of these programs.
  17. *
  18. * This disclaimer of warranty extends to the user of these programs
  19. * and user's customers, employees, agents, transferees, successors,
  20. * and assigns.
  21. *
  22. * The ITU does not represent or warrant that the programs furnished
  23. * hereunder are free of infringement of any third-party patents.
  24. * Commercial implementations of ITU-T Recommendations, including
  25. * shareware, may be subject to royalty fees to patent holders.
  26. * Information regarding the ITU-T patent policy is available from
  27. * the ITU Web site at http://www.itu.int.
  28. *
  29. * THIS IS NOT A GRANT OF PATENT RIGHTS - SEE THE ITU-T PATENT POLICY.
  30. ************************************************************************
  31. */
  32. /*!
  33.  *****************************************************************************
  34.  *
  35.  * file rtp.c
  36.  *
  37.  * brief
  38.  *    Functions to handle RTP headers and packets per RFC1889 and RTP NAL spec
  39.  *    Functions support little endian systems only (Intel, not Motorola/Sparc)
  40.  *
  41.  * date
  42.  *    30 September 2001
  43.  *
  44.  * author
  45.  *    Stephan Wenger   stewe@cs.tu-berlin.de
  46.  *****************************************************************************/
  47. #include <stdio.h>
  48. #include <stdlib.h>
  49. #include <string.h>
  50. #include <assert.h>
  51. #include <memory.h>
  52. #include "rtp.h"
  53. #include "elements.h"
  54. #include "defines.h"
  55. #include "global.h"
  56. // A little trick to avoid those horrible #if TRACE all over the source code
  57. #if TRACE
  58. #define SYMTRACESTRING(s) strncpy(sym.tracestring,s,TRACESTRING_SIZE)
  59. #else
  60. #define SYMTRACESTRING(s) // to nothing
  61. #endif
  62. int CurrentRTPTimestamp = 0;      //! The RTP timestamp of the current packet,
  63.                                   //! incremented with all P and I frames
  64. int CurrentRTPSequenceNumber = 0; //! The RTP sequence number of the current packet
  65.                                   //! incremented by one for each sent packet
  66. /*!
  67.  *****************************************************************************
  68.  *
  69.  * brief 
  70.  *    ComposeRTPpacket composes the complete RTP packet using the various
  71.  *    structure members of the RTPpacket_t structure
  72.  *
  73.  * return
  74.  *    0 in case of success
  75.  *    negative error code in case of failure
  76.  *
  77.  * para Parameters
  78.  *    Caller is responsible to allocate enough memory for the generated packet
  79.  *    in parameter->packet. Typically a malloc of 12+paylen bytes is sufficient
  80.  *
  81.  * para Side effects
  82.  *    none
  83.  *
  84.  * para Other Notes
  85.  *    Function contains assert() tests for debug purposes (consistency checks
  86.  *    for RTP header fields
  87.  *
  88.  * date
  89.  *    30 Spetember 2001
  90.  *
  91.  * author
  92.  *    Stephan Wenger   stewe@cs.tu-berlin.de
  93.  *****************************************************************************/
  94. int ComposeRTPPacket (RTPpacket_t *p)
  95. {
  96.   // Consistency checks through assert, only used for debug purposes
  97.   assert (p->v == 2);
  98.   assert (p->p == 0);
  99.   assert (p->x == 0);
  100.   assert (p->cc == 0);    // mixer designers need to change this one
  101.   assert (p->m == 0 || p->m == 1);
  102.   assert (p->pt < 128);
  103.   assert (p->seq < 65536);
  104.   assert (p->payload != NULL);
  105.   assert (p->paylen < 65536 - 40);  // 2**16 -40 for IP/UDP/RTP header
  106.   assert (p->packet != NULL);
  107.   // Compose RTP header, little endian
  108.   p->packet[0] = (   (p->v)
  109.                   |  (p->p << 2)
  110.                   |  (p->x << 3)
  111.                   |  (p->cc << 4) );
  112.   p->packet[1] = (   (p->m)
  113.                   |  (p->pt << 1) );
  114.   p->packet[2] = p->seq & 0xff;
  115.   p->packet[3] = (p->seq >> 8) & 0xff;
  116.   memcpy (&p->packet[4], &p->timestamp, 4);  // change to shifts for unified byte sex
  117.   memcpy (&p->packet[8], &p->ssrc, 4);// change to shifts for unified byte sex
  118.   // Copy payload 
  119.   memcpy (&p->packet[12], p->payload, p->paylen);
  120.   p->packlen = p->paylen+12;
  121.   return 0;
  122. }
  123. /*!
  124.  *****************************************************************************
  125.  *
  126.  * brief 
  127.  *    WriteRTPPacket writes the supplied RTP packet to the output file
  128.  *
  129.  * return
  130.  *    0 in case of access
  131.  *    <0 in case of write failure (typically fatal)
  132.  *
  133.  * para Parameters
  134.  *    p: the RTP packet to be written (after ComposeRTPPacket() )
  135.  *    f: output file
  136.  *
  137.  * para Side effects
  138.  *    none
  139.  *
  140.  * date
  141.  *    October 23, 2001
  142.  *
  143.  * author
  144.  *    Stephan Wenger   stewe@cs.tu-berlin.de
  145.  *****************************************************************************/
  146. int WriteRTPPacket (RTPpacket_t *p, FILE *f)
  147. {
  148.   int intime = -1;
  149.   assert (f != NULL);
  150.   assert (p != NULL);
  151.   if (1 != fwrite (&p->packlen, 4, 1, f))
  152.     return -1;
  153.   if (1 != fwrite (&intime, 4, 1, f))
  154.     return -1;
  155.   if (1 != fwrite (p->packet, p->packlen, 1, f))
  156.     return -1;
  157.   return 0;
  158. }
  159. /*!
  160.  *****************************************************************************
  161.  *
  162.  * brief 
  163.  *    ComposeHeaderPacketPayload generates the payload for a header packet
  164.  *    using the inp-> structure contents.  The header packet contains 
  165.  *    definitions for a single parameter set 0, which is used for all 
  166.  *    slices of the picture
  167.  *
  168.  * return
  169.  *    len of the genberated payload in bytes
  170.  *    <0 in case of failure (typically fatal)
  171.  *
  172.  * para Parameters
  173.  *    p: the payload of the RTP packet to be written
  174.  *
  175.  * para Side effects
  176.  *    none
  177.  *
  178.  * note
  179.  *    This function should be revisited and checked in case of additional
  180.  *    bit stream parameters that affect the picture header (or higher
  181.  *    entitries).  Typical examples are more entropy coding schemes, other
  182.  *    motion vector resolutiuon, and optional elements
  183.  *
  184.  * date
  185.  *    October 23, 2001
  186.  *
  187.  * author
  188.  *    Stephan Wenger   stewe@cs.tu-berlin.de
  189.  *****************************************************************************/
  190. int ComposeHeaderPacketPayload (byte *payload)
  191. {
  192.   int slen=0;
  193.   int multpred;
  194.   assert (img->width%16 == 0);
  195.   assert (img->height%16 == 0);
  196. #ifdef _ADDITIONAL_REFERENCE_FRAME_
  197.   if (input->no_multpred <= 1 && input->add_ref_frame == 0)
  198. #else
  199.   if (input->no_multpred <= 1)
  200. #endif
  201.     multpred=FALSE;
  202.   else
  203.     multpred=TRUE;               // multiple reference frames in motion search
  204.   
  205.   slen = snprintf (payload, MAXRTPPAYLOADLEN, 
  206.              "a=H26L (0) MaxPicID %d
  207.             na=H26L (0) UseMultpred %d
  208.             na=H26L (0) BufCycle %d
  209.             na=H26L (0) PixAspectRatioX 1
  210.             na=H26L (0) PixAspectRatioY 1
  211.             na=H26L (0) DisplayWindowOffsetTop 0
  212.             na=H26L (0) DisplayWindowOffsetBottom 0
  213.             na=H26L (0) DisplayWindowOffsetRight 0
  214.             na=H26L (0) DisplayWindowOffsetLeft 0
  215.             na=H26L (0) XSizeMB %d
  216.             na=H26L (0) YSizeMB %d
  217.             na=H26L (0) EntropyCoding %s
  218.             na=H26L (0) MotionResolution %s
  219.             na=H26L (0) PartitioningType %s
  220.             na=H26L (0) IntraPredictionType %s
  221.             na=H26L (0) HRCParameters 0
  222.             
  223.             na=H26L (-1) FramesToBeEncoded %d
  224.             na=H26L (-1) FrameSkip %d
  225.             na=H26L (-1) SequenceFileName %s
  226.             %c%c",
  227.             256,
  228.             multpred==TRUE?1:0,
  229.             input->no_multpred,
  230.             input->img_width/16,
  231.             input->img_height/16,
  232.             input->symbol_mode==UVLC?"UVLC":"CABAC",
  233.             input->mv_res==0?"quater":"eigth",
  234.             input->partition_mode==0?"one":"three",
  235.             input->UseConstrainedIntraPred==0?"InterPredicted":"NotInterPredicted",
  236.             input->no_frames,
  237.             input->jumpd,
  238.             input->infile,
  239.             4,     // Unix Control D EOF symbol
  240.             26);  // MS-DOS/Windows Control Z EOF Symbol
  241.   return slen;
  242. }
  243. /*!
  244.  *****************************************************************************
  245.  *
  246.  * brief 
  247.  *    void RTPSequenceHeader (FILE *out) write the RTP Sequence header in the
  248.  *       form of a header packet into the outfile.  It is assumed that the
  249.  *       input-> structure is already filled (config file is parsed)
  250.  *
  251.  * return
  252.  *    length of sequence header
  253.  *
  254.  * para Parameters
  255.  *    out: fiel pointer of the output file
  256.  *
  257.  * para Side effects
  258.  *    header written, statistics are updated, RTP sequence number updated
  259.  *
  260.  * para Note
  261.  *    This function uses alloca() to reserve memry on the stack -- no freeing and
  262.  *    no return value check necessary, error lead to stack overflows
  263.  *
  264.  * date
  265.  *    October 24, 2001
  266.  *
  267.  * author
  268.  *    Stephan Wenger   stewe@cs.tu-berlin.de
  269.  *****************************************************************************/
  270. int RTPSequenceHeader (FILE *out)
  271. {
  272.   RTPpacket_t *p;
  273.   assert (out != NULL);
  274.   // Set RTP structure elements and alloca() memory foor the buffers
  275.   p = (RTPpacket_t *) alloca (sizeof (RTPpacket_t));
  276.   p->packet=alloca (MAXRTPPACKETSIZE);
  277.   p->payload=alloca (MAXRTPPACKETSIZE);
  278.   p->v=2;
  279.   p->p=0;
  280.   p->x=0;
  281.   p->cc=0;
  282.   p->m=1;
  283.   p->pt=H26LPAYLOADTYPE;
  284.   p->seq=CurrentRTPSequenceNumber++;
  285.   p->timestamp=CurrentRTPTimestamp;
  286.   p->ssrc=H26LSSRC;
  287.   // Set First Byte of RTP payload, see VCEG-N72r1
  288.   p->payload[0] = 
  289.     6 |               // Parameter Update Packet
  290.     0 |               // no know error
  291.     0;                // reserved
  292.   // Generate the Parameter update SDP syntax, donm't overwrite First Byte
  293.   p->paylen = 1 + ComposeHeaderPacketPayload (&p->payload[1]);
  294.   // Generate complete RTP packet
  295.   if (ComposeRTPPacket (p) < 0)
  296.   {
  297.     printf ("Cannot compose RTP packet, exitn");
  298.     exit (-1);
  299.   }
  300.   if (WriteRTPPacket (p, out) < 0)
  301.   {
  302.     printf ("Cannot write %d bytes of RTP packet to outfile, exitn", p->packlen);
  303.     exit (-1);
  304.   }
  305.   return (p->packlen);
  306. }
  307. /*!
  308.  *****************************************************************************
  309.  *
  310.  * brief 
  311.  *    int RTPSliceHeader () write the Slice header for the RTP NAL      
  312.  *
  313.  * return
  314.  *    Number of bits used by the slice header
  315.  *
  316.  * para Parameters
  317.  *    none
  318.  *
  319.  * para Side effects
  320.  *    Slice header as per VCEG-N72r2 is written into the appropriate partition
  321.  *    bit buffer
  322.  *
  323.  * para Limitations/Shortcomings/Tweaks
  324.  *    The current code does not support the change of picture parameters within
  325.  *    one coded sequence, hence there is only one parameter set necessary.  This
  326.  *    is hard coded to zero.
  327.  *    As per Email deiscussions on 10/24/01 we decided to include the SliceID
  328.  *    into both the Full Slice pakcet and Partition A packet
  329.  *   
  330.  * date
  331.  *    October 24, 2001
  332.  *
  333.  * author
  334.  *    Stephan Wenger   stewe@cs.tu-berlin.de
  335.  *****************************************************************************/
  336. int RTPSliceHeader()
  337. {
  338.   int dP_nr = assignSE2partition[input->partition_mode][SE_HEADER];
  339.   Bitstream *currStream = ((img->currentSlice)->partArr[dP_nr]).bitstream;
  340.   DataPartition *partition = &((img->currentSlice)->partArr[dP_nr]);
  341.   SyntaxElement sym;
  342.   int len = 0;
  343.   int RTPSliceType;
  344.   assert (input->of_mode == PAR_OF_RTP);
  345.   sym.type = SE_HEADER;         // This will be true for all symbols generated here
  346.   sym.mapping = n_linfo2;       // Mapping rule: Simple code number to len/info
  347.   SYMTRACESTRING("RTP-SH: Parameter Set");
  348.   sym.value1 = 0;
  349.   len += writeSyntaxElement_UVLC (&sym, partition);
  350.   SYMTRACESTRING("RTP-SH: Picture ID");
  351.   sym.value1 = img->currentSlice->picture_id;
  352. // printf ("Put PictureId %dn", img->currentSlice->picture_id);
  353.   len += writeSyntaxElement_UVLC (&sym, partition);
  354.   /*! StW:
  355.   // Note: we currently do not support mixed slice types in the encoder, hence
  356.   // we use the picture type here (although there is no such thing as a picture
  357.   // type any more)
  358.   //
  359.   // This needs to be double checked against the document.  Email inquiery on
  360.   // 10/24 evening: is there a need for distinguishing the multpred P from regular
  361.   // P?  if so, this has to be revisited! 
  362.   //
  363.   // StW bug fix: write Slice type according to document
  364.   */
  365.   switch (img->type)
  366.   {
  367.     case INTER_IMG:
  368.       if (img->types==SP_IMG)
  369.         RTPSliceType = 2;
  370.       else
  371.         RTPSliceType = 0;
  372.       break;
  373.     case INTRA_IMG:
  374.       RTPSliceType = 3;
  375.       break;
  376.     case B_IMG:
  377.       RTPSliceType = 1;
  378.       break;
  379.     case SP_IMG:
  380.       // That's what I would expect to be the case. But img->type contains INTER_IMG 
  381.       // here (see handling above)
  382.       //! todo make one variable from img->type and img->types
  383.       RTPSliceType = 2;
  384.       break;
  385.     default:
  386.       printf ("Panic: unknown picture type %d, exitn", img->type);
  387.       exit (-1);
  388.   }
  389.   SYMTRACESTRING("RTP-SH: Slice Type");
  390.   sym.value1 = RTPSliceType;
  391.   len += writeSyntaxElement_UVLC (&sym, partition);
  392.   SYMTRACESTRING("RTP-SH: FirstMBInSliceX");
  393.   sym.value1 = img->mb_x;
  394.   len += writeSyntaxElement_UVLC (&sym, partition);
  395.   SYMTRACESTRING("RTP-SH: FirstMBinSlinceY");
  396.   sym.value1 = img->mb_y;
  397.   len += writeSyntaxElement_UVLC (&sym, partition);
  398.   SYMTRACESTRING("RTP-SH: InitialQP");
  399.   sym.value1 = 31-img->qp;
  400.   len += writeSyntaxElement_UVLC (&sym, partition);
  401.   if (img->types==SP_IMG)
  402.   {
  403.     SYMTRACESTRING("RTP-SH: SP InitialQP");
  404.     sym.value1 = 31-img->qpsp;
  405.     len += writeSyntaxElement_UVLC (&sym, partition);
  406.   }
  407.   /*! StW:
  408.   // Note: VCEG-N72 says that the slice type UVLC is not present in single
  409.   // slice packets.  Generally, the NAL allows to mix Single Slice and Partitioning,
  410.   // however, the software does not.  Hence it is sufficient here to express
  411.   // the dependency by checkling the input parameter
  412.   */
  413.   if (input->partition_mode == PAR_DP_3)
  414.   {
  415.     SYMTRACESTRING("RTP-SH: Slice ID");
  416.     sym.value1 = img->current_slice_nr;
  417.     len += writeSyntaxElement_UVLC (&sym, partition);
  418.   }
  419.   // After this, and when in CABAC mode, terminateSlice() may insert one more
  420.   // UVLC codeword for the number of coded MBs
  421.   return len;
  422. }
  423. /*!
  424.  *****************************************************************************
  425.  *
  426.  * brief 
  427.  *    int RTPWriteBits (int marker) write the Slice header for the RTP NAL      
  428.  *
  429.  * return
  430.  *    Number of bytes written to output file
  431.  *
  432.  * para Parameters
  433.  *    marker: markber bit,
  434.  *
  435.  * para Side effects
  436.  *    Packet written, RTPSequenceNumber and RTPTimestamp updated
  437.  *   
  438.  * date
  439.  *    October 24, 2001
  440.  *
  441.  * author
  442.  *    Stephan Wenger   stewe@cs.tu-berlin.de
  443.  *****************************************************************************/
  444. int RTPWriteBits (int Marker, int PacketType, void * bitstream, 
  445.                     int BitStreamLenInByte, FILE *out)
  446. {
  447.   RTPpacket_t *p;
  448.   assert (out != NULL);
  449.   assert (BitStreamLenInByte < 65000);
  450.   assert (bitstream != NULL);
  451.   assert (PacketType < 4);
  452.   // Set RTP structure elements and alloca() memory foor the buffers
  453.   p = (RTPpacket_t *) alloca (sizeof (RTPpacket_t));
  454.   p->packet=alloca (MAXRTPPACKETSIZE);
  455.   p->payload=alloca (MAXRTPPACKETSIZE);
  456.   p->v=2;
  457.   p->p=0;
  458.   p->x=0;
  459.   p->cc=0;
  460.   p->m=Marker&1;
  461.   p->pt=H26LPAYLOADTYPE;
  462.   p->seq=CurrentRTPSequenceNumber++;
  463.   p->timestamp=CurrentRTPTimestamp;
  464.   p->ssrc=H26LSSRC;
  465.   p->payload[0] = PacketType;
  466.   p->paylen = 1 + BitStreamLenInByte;
  467.   memcpy (&p->payload[1], bitstream, BitStreamLenInByte);
  468.   // Generate complete RTP packet
  469.   if (ComposeRTPPacket (p) < 0)
  470.   {
  471.     printf ("Cannot compose RTP packet, exitn");
  472.     exit (-1);
  473.   }
  474.   if (WriteRTPPacket (p, out) < 0)
  475.   {
  476.     printf ("Cannot write %d bytes of RTP packet to outfile, exitn", p->packlen);
  477.     exit (-1);
  478.   }
  479.   return (p->packlen);
  480. }
  481. static int oldtr = -1;
  482. void RTPUpdateTimestamp (int tr)
  483. {
  484.   int delta;
  485.   if (oldtr == -1)            // First invocation
  486.   {
  487.     CurrentRTPTimestamp = 0;  //! This is a violation of the security req. of
  488.                               //! RTP (random timestamp), but easier to debug
  489.     oldtr = 0;
  490.     return;
  491.   }
  492.   /*! The following code assumes a wrap around of TR at 256, and
  493.       needs to be changed as soon as this is no more true.
  494.       
  495.       The support for B frames is a bit tricky, because it is not easy to distinguish
  496.       between a natural wrap-around of the tr, and the intentional going back of the
  497.       tr because of a B frame.  It is solved here by a heuristic means: It is assumed that
  498.       B frames are never "older" than 10 tr ticks.  Everything higher than 10 is considered
  499.       a wrap around.
  500.       I'm a bit at loss whether this is a fundamental problem of B frames.  Does a decoder
  501.       have to change its TR interpretation depenent  on the picture type?  Horrible -- we
  502.       would have a fundamental problem when mixing slices.  This needs careful review.
  503.   */
  504.   delta = tr - oldtr;
  505.   if (delta < -10)        // wrap-around
  506.     delta+=256;
  507.   CurrentRTPTimestamp += delta * RTP_TR_TIMESTAMP_MULT;
  508.   oldtr = tr;
  509. }