SdpMedia.cxx
上传用户:sy_wanhua
上传日期:2013-07-25
资源大小:3048k
文件大小:15k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

C/C++

  1. /* ====================================================================
  2.  * The Vovida Software License, Version 1.0 
  3.  * 
  4.  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
  5.  * 
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 
  10.  * 1. Redistributions of source code must retain the above copyright
  11.  *    notice, this list of conditions and the following disclaimer.
  12.  * 
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in
  15.  *    the documentation and/or other materials provided with the
  16.  *    distribution.
  17.  * 
  18.  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
  19.  *    and "Vovida Open Communication Application Library (VOCAL)" must
  20.  *    not be used to endorse or promote products derived from this
  21.  *    software without prior written permission. For written
  22.  *    permission, please contact vocal@vovida.org.
  23.  *
  24.  * 4. Products derived from this software may not be called "VOCAL", nor
  25.  *    may "VOCAL" appear in their name, without prior written
  26.  *    permission of Vovida Networks, Inc.
  27.  * 
  28.  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
  29.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
  31.  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
  32.  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
  33.  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
  34.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  35.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  36.  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  37.  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  38.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  39.  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  40.  * DAMAGE.
  41.  * 
  42.  * ====================================================================
  43.  * 
  44.  * This software consists of voluntary contributions made by Vovida
  45.  * Networks, Inc. and many individuals on behalf of Vovida Networks,
  46.  * Inc.  For more information on Vovida Networks, Inc., please see
  47.  * <http://www.vovida.org/>.
  48.  *
  49.  */
  50. static const char* const SdpMedia_cxx_Version =
  51.     "$Id: SdpMedia.cxx,v 1.17 2001/06/15 00:28:46 chok Exp $";
  52. #include <string>
  53. #include "support.hxx"
  54. #include "SdpExceptions.hxx"
  55. #include "SdpMedia.hxx"
  56. ///
  57. SdpMedia::SdpMedia()
  58. {
  59.     mediaType = MediaTypeAudio;
  60.     mediaTypeString = "audio";
  61.     port = -1;
  62.     numPorts = 0;
  63.     transportType = TransportTypeRTP;
  64.     formatList.clear();
  65.     formatList.push_back( "0" );
  66.     formatListInt.clear();
  67.     formatListInt.push_back( 0 );
  68.     mediaAttrib = 0;
  69.     connection = 0;
  70.     bandwidth = 0;
  71.     encryptkey = 0;
  72.     mediaInfo = "";
  73. }    // SdpMedia::SdpMedia
  74. ///
  75. SdpMedia::SdpMedia (split_t& mediaDetails)
  76. {
  77.     //initialize all pointers
  78.     bandwidth = 0;
  79.     mediaAttrib = 0;
  80.     connection = 0;
  81.     encryptkey = 0;
  82.     split_t::iterator linecount;
  83.     linecount = mediaDetails.begin();
  84.     //print Media details
  85.     split_t::iterator tempcount;
  86.     tempcount = mediaDetails.begin();
  87.     while (tempcount != mediaDetails.end())
  88.     {
  89.         cpLog(LOG_DEBUG_STACK, "SdpMedia: %s", (*tempcount).c_str());
  90.         tempcount++;
  91.     }
  92.     while (linecount != mediaDetails.end())
  93.     {
  94.         if ((*linecount)[0] == 'm')
  95.         {
  96.             string lineStr = (*linecount);
  97.             lineStr.erase(0, 2);
  98.             chomp (&lineStr);
  99.             split_t mList(split(lineStr, " "));
  100.             if (mList.size() < 4)
  101.             {
  102.                 cpLog(LOG_ERR, "SdpMedia: m= size < 4");
  103.                 throw SdpExceptions(PARAM_NUMERR);
  104.             }
  105.             else
  106.                 cpLog(LOG_DEBUG_STACK, "SdpMedia:m size >4");
  107.             //parse media items.
  108.             split_t::iterator mListIter;
  109.             mListIter = mList.begin();
  110.             mediaTypeString = *mListIter;
  111.             if (mediaTypeString == string("audio"))
  112.             {
  113.                 mediaType = MediaTypeAudio;
  114.                 cpLog(LOG_DEBUG_STACK, "Found m=audio");
  115.             }
  116.             else if (mediaTypeString == string("video"))
  117.             {
  118.                 mediaType = MediaTypeVideo;
  119.                 cpLog(LOG_DEBUG_STACK, "Found m=video");
  120.             }
  121.             else
  122.             {
  123.                 mediaType = MediaTypeUnknown;
  124.                 cpLog( LOG_DEBUG_STACK, "Found m=%s", mediaTypeString.c_str() );
  125.             }
  126.             ++mListIter;
  127.             /** port may be <port>/<num of ports>
  128.                 So, split mListIter again on /  */
  129.             string portDetails = (*mListIter);
  130.             split_t portList(split(portDetails, "/"));
  131.             port = strtol(portList[0].c_str(), (char**)NULL, 10);
  132.             cpLog(LOG_DEBUG_STACK, "SDP port: %d " , port);
  133.             if (portList.size() == 2)
  134.             {
  135.                 //contains the number of ports.
  136.                 numPorts = atoi(portList[1].c_str());
  137.             }
  138.             else
  139.             {
  140.                 numPorts = 0;
  141.             }
  142.             ++mListIter;
  143.             if (*mListIter == SdpMediaTransportRTPAVP)
  144.             {
  145.                 transportType = TransportTypeRTP;
  146.             }
  147.             else if (*mListIter == SdpMediaTransportUDP)
  148.             {
  149.                 transportType = TransportTypeUDP;
  150.             }
  151.             //handle the format list.
  152.             formatList.clear();
  153.             formatListInt.clear();
  154.             char format[ MaxFormatIntValue+1 ];
  155.             format[ MaxFormatIntValue ] = '';
  156.             char* endPtr = 0;
  157.             int formatInt = 0;
  158.             ++mListIter;
  159.             while (mListIter != mList.end())
  160.             {
  161.                 //these are all format list items
  162.                 cpLog( LOG_DEBUG_STACK, "Media format: %s", (*mListIter).c_str() );
  163.                 formatList.push_back( *mListIter );
  164.                 strncpy( format, (*mListIter).c_str(), MaxFormatIntValue );
  165.                 formatInt = strtol( format, &endPtr, 10 );
  166.                 if( endPtr == format )    // Format is not an integer
  167.                 {
  168.                     cpLog( LOG_DEBUG, "Non-integer media format: %s", (*mListIter).c_str() );
  169.                 }
  170.                 else                      // Format is an integer
  171.                 {
  172.                     cpLog( LOG_DEBUG, "Integer media format: %d", formatInt );
  173.                     formatListInt.push_back( formatInt );
  174.                 }
  175.                 ++mListIter;
  176.             }
  177.         }// if line = m.
  178.         else if ((*linecount)[0] == 'a')
  179.         {
  180.             try
  181.             {
  182.                 if (!mediaAttrib)
  183.                 {
  184.                     //create the MediaAttribute object.
  185.                     mediaAttrib = new MediaAttributes();
  186.                     assert(mediaAttrib);
  187.                 }
  188.                 string attrib = (*linecount);
  189.                 attrib.erase(0, 2);
  190.                 chomp (&attrib);
  191.                 mediaAttrib->setAttribute(attrib);
  192.             }
  193.             catch (SdpExceptions& exp)
  194.             {
  195.                 throw SdpExceptions(FAILED);
  196.             }
  197.         }
  198.         else if ((*linecount)[0] == 'b')
  199.         {
  200.             try
  201.             {
  202.                 string bw = (*linecount);
  203.                 bw.erase(0, 2);
  204.                 chomp (&bw);
  205.                 cpLog(LOG_DEBUG_STACK, "Bandwidth, before sending to C'tor:%s", bw.c_str());
  206.                 bandwidth = new SdpBandwidth(bw);
  207.                 assert(bandwidth);
  208.             }
  209.             catch (SdpExceptions& exp)
  210.             {
  211.                 throw SdpExceptions(FAILED);
  212.             }
  213.         }
  214.         else if ((*linecount)[0] == 'k')
  215.         {
  216.             try
  217.             {
  218.                 if (encryptkey)
  219.                 {
  220.                     delete encryptkey;
  221.                     encryptkey = 0;
  222.                 }
  223.                 string key = (*linecount);
  224.                 key.erase(0, 2);
  225.                 chomp (&key);
  226.                 cpLog(LOG_DEBUG, "Encryption key, before sending to C'tor:%s", key.c_str());
  227.                 encryptkey = new SdpEncryptkey(key);
  228.                 assert(encryptkey);
  229.             }
  230.             catch (SdpExceptions& exp)
  231.             {
  232.                 throw SdpExceptions(FAILED);
  233.             }
  234.         }
  235.         else if ((*linecount)[0] == 'c')
  236.         {
  237.             try
  238.             {
  239.                 string conn = (*linecount);
  240.                 conn.erase(0, 2);
  241.                 chomp (&conn);
  242.                 connection = new SdpConnection(conn);
  243.                 assert(connection);
  244.             }
  245.             catch (SdpExceptions& exp)
  246.             {
  247.                 throw SdpExceptions(FAILED);
  248.             }
  249.         }
  250.         else if ((*linecount)[0] == 'i')
  251.         {
  252.             string info = (*linecount);
  253.             info.erase(0, 2);
  254.             chomp (&info);
  255.             mediaInfo = info;
  256.         }
  257.         else if ((*linecount)[0] == 'r' || (*linecount)[0] == 'n' )
  258.         {
  259.             //TODO make sure this is ok
  260.             cpLog( LOG_DEBUG_STACK, "Empty line" );
  261.         }
  262.         else
  263.         {
  264.             cpLog(LOG_ERR, "Unknown field in the media portion %s",
  265.                   (*linecount).c_str());
  266.             throw SdpExceptions(UNKNOWN_FIELD);
  267.         }
  268.         linecount++;
  269.     }    // while
  270. }    // SdpMedia::SdpMedia(split_t& mediaDetails)
  271. ///
  272. const SdpMedia&
  273. SdpMedia::operator=(SdpMedia& newMedia)
  274. {
  275.     mediaType = newMedia.mediaType;
  276.     mediaTypeString = newMedia.mediaTypeString;
  277.     port = newMedia.port;
  278.     numPorts = newMedia.numPorts;
  279.     transportType = newMedia.transportType;
  280.     mediaInfo = newMedia.mediaInfo;
  281.     cpLog(LOG_DEBUG_STACK, "Copied media, port, numPorts, transportType");
  282.     vector < string > * newFormatList = newMedia.getStringFormatList();
  283.     assert(newFormatList);
  284.     formatList = *newFormatList;
  285.     vector < int > * newIntFormatList = newMedia.getFormatList();
  286.     if( newIntFormatList != 0 )
  287.     {
  288.         formatListInt = *(newMedia.getFormatList());
  289.     }
  290.     else
  291.     {
  292.         formatListInt.clear();
  293.     }
  294.     cpLog(LOG_DEBUG_STACK, "SdpMedia: copied the format list");
  295.     if (newMedia.mediaAttrib)
  296.     {
  297.         if (!mediaAttrib)
  298.         {
  299.             mediaAttrib = new MediaAttributes;
  300.             assert(mediaAttrib);
  301.         }
  302.         *(mediaAttrib) = *(newMedia.mediaAttrib);
  303.         //copy parent details.
  304. //        *((SdpAttributes*)(mediaAttrib)) = *((SdpAttributes*)(newMedia.mediaAttrib));
  305.         cpLog(LOG_DEBUG_STACK, "SdpMedia: Copied Media attributes");
  306.     }
  307.     else //if not defined now, but previously defined, remove previous definition.
  308.     {
  309.         if (mediaAttrib)
  310.         {
  311.             delete mediaAttrib;
  312.             mediaAttrib = 0;
  313.         }
  314.     }
  315.     if (newMedia.connection)
  316.     {
  317.         if (!connection)
  318.         {
  319.             connection = new SdpConnection;
  320.             assert(connection);
  321.         }
  322.         *(connection) = *(newMedia.connection);
  323.         cpLog(LOG_DEBUG_STACK, "SdpMedia: copied connection");
  324.     }
  325.     else
  326.     {
  327.         if (connection)
  328.         {
  329.             delete connection;
  330.             connection = 0;
  331.         }
  332.     }
  333.     if (newMedia.bandwidth)
  334.     {
  335.         if (!bandwidth)
  336.         {
  337.             bandwidth = new SdpBandwidth;
  338.             assert(bandwidth);
  339.         }
  340.         *(bandwidth) = *(newMedia.bandwidth);
  341.         cpLog(LOG_DEBUG_STACK, "SdpMedia:copied bandwidth");
  342.     }
  343.     else
  344.     {
  345.         if (bandwidth)
  346.         {
  347.             delete bandwidth;
  348.             bandwidth = 0;
  349.         }
  350.     }
  351.     if (newMedia.encryptkey)
  352.     {
  353.         if (!encryptkey)
  354.         {
  355.             encryptkey = new SdpEncryptkey;
  356.             assert(encryptkey);
  357.         }
  358.         *(encryptkey) = *(newMedia.encryptkey);
  359.         cpLog(LOG_DEBUG, "SdpEncryptkey:copied encryptkey");
  360.     }
  361.     else
  362.     {
  363.         if (encryptkey)
  364.         {
  365.             delete encryptkey;
  366.             encryptkey = 0;
  367.         }
  368.     }
  369.     return *(this);
  370. }
  371. ///
  372. string
  373. SdpMedia::transportTypeString ()
  374. {
  375.     string s;
  376.     switch (transportType)
  377.     {
  378.         case TransportTypeRTP:
  379.         {
  380.             s = SdpMediaTransportRTPAVP;
  381.             break;
  382.         }
  383.         case TransportTypeUDP:
  384.         {
  385.             s = SdpMediaTransportUDP;
  386.             break;
  387.         }
  388.         default:
  389.         {
  390.             //TODO Throw some exception
  391.             break;
  392.         }
  393.     }
  394.     return s;
  395. }    // SdpMedia::transportTypeString
  396. ///
  397. void
  398. SdpMedia::encodeMediaAnnouncement (ostrstream& s)
  399. {
  400.     s << "m="
  401.       << mediaTypeString
  402.       << ' '
  403.       << port;
  404.     if (numPorts > 0)
  405.     {
  406.         s << '/' << numPorts;
  407.     }
  408.     s << ' ' << transportTypeString();
  409.     vector < string > ::iterator iter = formatList.begin();
  410.     while (iter != formatList.end())
  411.     {
  412.         s << ' ' << *iter;
  413.         ++iter;
  414.     }
  415.     s << "rn";
  416. }    // SdpMedia::encodeMediaAnnouncement
  417. ///
  418. void
  419. SdpMedia::setTransportType(TransportType newtransport)
  420. {
  421.     //TODO relax these checks?
  422.     switch (newtransport)
  423.     {
  424.         case TransportTypeRTP:
  425.         if (((port > 1023) && (port < 65536)) && (0 == (port % 2)))
  426.             transportType = newtransport;
  427.         else
  428.             cpLog(LOG_ERR, "for RTP, port: %d should be within 1024 - 65536 and even", port);
  429.         break;
  430.         case TransportTypeUDP:
  431.         if ((port > 1023) && (port < 65536))
  432.             transportType = newtransport;
  433.         else
  434.             cpLog(LOG_ERR, "for UDP, port: %d should be within 1024 - 65536", port);
  435.         break;
  436.         default:
  437.         cpLog(LOG_ERR, "Unknown transport type %d", newtransport);
  438.     }
  439. }
  440. ///
  441. void
  442. SdpMedia::encode (ostrstream& s)
  443. {
  444.     // m= media name and transport address
  445.     encodeMediaAnnouncement (s);
  446.     // i=* media title
  447.     if (mediaInfo.size() > 0)
  448.     {
  449.         s << "i=" << mediaInfo << "rn";
  450.     }
  451.     // c=* connection information (not required if included at session-level)
  452.     if (connection)
  453.     {
  454.         connection->encode (s);
  455.     }
  456.     // b=* bandwidth information
  457.     if (bandwidth)
  458.     {
  459.         bandwidth->encode (s);
  460.     }
  461.     // k=* encryption key
  462.     if (encryptkey)
  463.     {
  464.         encryptkey->encode (s);
  465.     }
  466.     // a=* zero or more session attribute lines
  467.     if (mediaAttrib)
  468.     {
  469.         mediaAttrib->encode (s);
  470.     }
  471. }    // SdpMedia::encode
  472. void
  473. SdpMedia::setMediaType( SdpMediaType newType )
  474. {
  475.     switch( newType )
  476.     {
  477.         case MediaTypeAudio:
  478.         {
  479.             mediaTypeString = "audio";
  480.         }
  481.         break;
  482.         case MediaTypeVideo:
  483.         {
  484.             mediaTypeString = "video";
  485.         }
  486.         break;
  487.         default:
  488.         {
  489.             cpLog( LOG_ERR, "Unknown media type %d", newType );
  490.             mediaTypeString = "unknown";
  491.         }
  492.     }
  493. }    // SdpMedia::setMediaType
  494. void
  495. SdpMedia::setMediaType( string newType )
  496. {
  497.     mediaTypeString = newType;
  498.     if( newType == "audio" )
  499.     {
  500.         mediaType = MediaTypeAudio;
  501.     }
  502.     else if( newType == "video" )
  503.     {
  504.         mediaType = MediaTypeVideo;
  505.     }
  506.     else
  507.     {
  508.         mediaType = MediaTypeUnknown;
  509.     }
  510. }    // SdpMedia::setMediaType