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

流媒体/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 281421,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 RtspFileWav_cxx_version =
  51.     "$Id: RtspFileWav.cxx,v 1.18 2001/07/26 21:47:01 kle Exp $";
  52. #include "RtspFileWav.hxx"
  53. #include "RtpFileTypes.hxx"
  54. RtspFileWav::RtspFileWav(const string& shortFilename)
  55.     : RtspFile( shortFilename ),
  56.       m_xAudioFile( 0 )
  57. {
  58.     myFileMode = RTSP_FILE_MODE_UNKNOWN;
  59. }
  60. RtspFileWav::~RtspFileWav()
  61. {
  62.     close();
  63. }
  64. bool
  65. RtspFileWav::saveHeader( const int ftIndex, RtspSdp& rtspSdp )
  66. {
  67.     // check filemap contains full codec information
  68.     if( rtpFileTypeInfo[ftIndex].WavFileFormat == 0x0000 )
  69.     {
  70.         cpLog( LOG_ERR, "Incomplete rtpFileTypeInfo map for codec %s",
  71.                rtpFileTypeInfo[ftIndex].name.c_str() );
  72.         return false;
  73.     }
  74.     mySfInfo.format = SF_FORMAT_WAV | SF_FORCE_OPEN;
  75.     mySfInfo.format_tag = rtpFileTypeInfo[ftIndex].WavFileFormat;
  76.     mySfInfo.samplerate = 8000;
  77.     mySfInfo.channels = 1;
  78.     mySfInfo.pcmbitwidth = 16;
  79.     mySfInfo.samples = 0;
  80.     mySfInfo.sections = 1;
  81.     mySfInfo.seekable = 1;
  82.     mySfInfo.bytewidth = rtpFileTypeInfo[ftIndex].bytewidth;
  83.     //TODO add WAVEFORMATEX extra bytes here
  84.     mySfInfo.avg_bytes_per_sec = (int)( (
  85.                                   (float)rtpFileTypeInfo[ftIndex].packetSize /
  86.                                   (float)rtpFileTypeInfo[ftIndex].intervalMs ) *
  87.                                   1000.0 );
  88.     cpLog( LOG_DEBUG, "mySfInfo.avg_bytes_per_sec %d", mySfInfo.avg_bytes_per_sec );
  89.     if( mySfInfo.avg_bytes_per_sec > 500 )
  90.     {
  91.         cpLog( LOG_DEBUG, "fixing mySfInfo.avg_bytes_per_sec to 0" );
  92.         mySfInfo.avg_bytes_per_sec = 0;
  93.     }
  94.     // save sf_info to file
  95.     SNDFILE* xAudioFile = sf_open_write( localFilename().getData(), &mySfInfo );
  96.     if( !xAudioFile )
  97.     {
  98.         cpLog( LOG_DEBUG, "sf_open_write %s - failed while saving header",
  99.                localFilename().getData() );
  100.         return false;
  101.     }
  102.     dummyWrite( xAudioFile, rtpFileTypeInfo[ftIndex].packetSize );
  103.     if( cpLogGetPriority() >= LOG_DEBUG )
  104.     {
  105.         printSfInfo();
  106.     }
  107.     // close audio file
  108.     sf_close( xAudioFile );
  109.     return true;
  110. }
  111. bool
  112. RtspFileWav::loadHeader( int* ftIndex, int* lengthInMs )
  113. {
  114.     *ftIndex = 0;
  115.     *lengthInMs = 0;
  116.     // read sf_info from file
  117.     memset( &mySfInfo, 0, sizeof( mySfInfo ) );
  118.     mySfInfo.format = SF_FORCE_OPEN;
  119.     SNDFILE* xAudioFile = sf_open_read( localFilename().getData(), &mySfInfo );
  120.     if( !xAudioFile )
  121.     {
  122.         char errbuff[80];
  123.         sf_error_str( xAudioFile, errbuff, 80 );
  124.         cpLog( LOG_ERR, "sf_open_read %s - failed: %s ",
  125.                localFilename().getData(), errbuff );
  126.         return false;
  127.     }
  128.     if( ( mySfInfo.format & SF_FORMAT_TYPEMASK ) != SF_FORMAT_WAV )
  129.     {
  130.         cpLog( LOG_ERR, "Audio file header doesn't match file extension" );
  131.         sf_close( xAudioFile );
  132.         return false;
  133.     }
  134.     
  135.     // read codec number from sf_info
  136.     *ftIndex = 0;
  137.     for( int i = 0; i< myNumberOfCodecs; i++ )
  138.     {
  139.         if( rtpFileTypeInfo[i].WavFileFormat == mySfInfo.format_tag )
  140.         {
  141.             *ftIndex = i;
  142.             cpLog( LOG_DEBUG, "Read index %d from audio map", i );
  143.             break;
  144.         }
  145.     }
  146.     if( *ftIndex == 0 )
  147.     {
  148.         cpLog( LOG_DEBUG, "Wav codec %d not found", mySfInfo.format_tag );
  149.         sf_close( xAudioFile );
  150.         return false;
  151.     }
  152.     //dirty hack of libsndfile
  153.     cpLog( LOG_DEBUG, "Filling incomplete SF_INFO structure" );
  154.     mySfInfo.pcmbitwidth = 16;
  155.     mySfInfo.bytewidth = rtpFileTypeInfo[*ftIndex].bytewidth;
  156.     sf_set_bytewidth( xAudioFile, &mySfInfo );
  157.     sf_close( xAudioFile );
  158.     if( cpLogGetPriority() >= LOG_DEBUG )
  159.     {
  160.         printSfInfo();
  161.     }
  162.     // calculate file length
  163.     if( rtpFileTypeInfo[*ftIndex].bytewidth > 2 )
  164.     {
  165.         *lengthInMs = int( mySfInfo.samples *
  166.                            rtpFileTypeInfo[*ftIndex].intervalMs );
  167.     }
  168.     else
  169.     {
  170.         *lengthInMs = int( mySfInfo.samples /
  171.                            ( (float)rtpFileTypeInfo[*ftIndex].packetSize /
  172.                              (float)rtpFileTypeInfo[*ftIndex].intervalMs ) );
  173.     }
  174.     cpLog( LOG_DEBUG, "File length is %d ms", *lengthInMs );
  175.     return true;
  176. }
  177. bool
  178. RtspFileWav::open( bool bReadWrite, int ftIndex )
  179. {
  180.     if( !bReadWrite ) //read mode
  181.     {
  182.         m_xAudioFile = sf_open_read( localFilename().getData(), &mySfInfo );
  183.         if( !m_xAudioFile )
  184.         {
  185.             cpLog( LOG_ERR, "sf_open_read %s - failed",
  186.                    localFilename().getData() );
  187.             return false;
  188.         }
  189.         cpLog( LOG_ERR, "Filling incomplete SF_INFO structure:" );
  190.         //dirty hack of libsndfile
  191.         mySfInfo.pcmbitwidth = 16;
  192.         mySfInfo.bytewidth = rtpFileTypeInfo[ftIndex].bytewidth;
  193.         sf_set_bytewidth( m_xAudioFile, &mySfInfo );
  194.         myFileMode = RTSP_FILE_MODE_PLAY;
  195.     }
  196.     else //write mode
  197.     {
  198.         mySfInfo.format = SF_FORMAT_WAV | SF_FORCE_OPEN;
  199.         mySfInfo.bytewidth = rtpFileTypeInfo[ftIndex].bytewidth;
  200.         m_xAudioFile = sf_open_write( localFilename().getData(), &mySfInfo );
  201.         if( !m_xAudioFile )
  202.         {
  203.             cpLog( LOG_ERR, "sf_open_write %s - failed",
  204.                    localFilename().getData() );
  205.             return false;
  206.         }
  207.         dummyWrite( m_xAudioFile, rtpFileTypeInfo[ftIndex].packetSize );
  208.         myFileMode = RTSP_FILE_MODE_REC;
  209.     }
  210.     return true;
  211. }
  212. bool
  213. RtspFileWav::close()
  214. {
  215.     if( m_xAudioFile )
  216.     {
  217.         if( sf_close( m_xAudioFile ) != 0 )
  218.         {
  219.             cpLog( LOG_ERR, "Error in sf_close()" );
  220.         }
  221.         m_xAudioFile = 0;
  222.         updateSdpFileRange();
  223.         return true;
  224.     }
  225.     return false;
  226. }
  227. int
  228. RtspFileWav::read( void* data, int max, 
  229.                    unsigned short* pSeqNum, unsigned int* pTS )
  230. {
  231.     return sf_read_raw( m_xAudioFile, data, max );
  232. }
  233. int
  234. RtspFileWav::write( void* data, int max, 
  235.                     unsigned short uSeqNum, unsigned int uTS )
  236. {
  237.     return sf_write_raw( m_xAudioFile, data, max );
  238. }
  239. long
  240. RtspFileWav::seek( const long samples, const int whence )
  241. {
  242.     return sf_seek( m_xAudioFile, samples, whence );
  243. }
  244. void
  245. RtspFileWav::printSfInfo() const
  246. {
  247.     printf( "    Sample Rate : %dn",   mySfInfo.samplerate );
  248.     printf( "    Samples     : %dn",   mySfInfo.samples );
  249.     printf( "    Channels    : %dn",   mySfInfo.channels );
  250.     printf( "    Bit Width   : %dn",   mySfInfo.pcmbitwidth );
  251.     printf( "    Format      : 0x%xn", mySfInfo.format );
  252.     printf( "    Format_tag* : 0x%xn", mySfInfo.format_tag );
  253.     printf( "    Bytewidth*  : %dn",   mySfInfo.bytewidth );
  254.     printf( "    Sections    : %dn",   mySfInfo.sections );
  255.     printf( "    Seekable    : %dn",   mySfInfo.seekable );
  256.     printf( "    Avg_bytes   : %dn",   mySfInfo.avg_bytes_per_sec );
  257. }
  258. void
  259. RtspFileWav::dummyWrite( SNDFILE* xAudioFile, const int dummyLen )
  260. {
  261.     // write some dummy data
  262.     cpLog( LOG_DEBUG, "Writing %d bytes of dummy data", dummyLen );
  263.     char dummyBuffer[dummyLen];
  264.     memset( dummyBuffer, 0, dummyLen );
  265.     if( (int)sf_write_raw( xAudioFile, dummyBuffer, dummyLen ) != dummyLen )
  266.     {
  267.         cpLog( LOG_DEBUG, "sf_write_raw result error %d", dummyLen );
  268.     }
  269. }
  270. /* Local Variables: */
  271. /* c-file-style: "stroustrup" */
  272. /* indent-tabs-mode: nil */
  273. /* c-file-offsets: ((access-label . -) (inclass . ++)) */
  274. /* c-basic-offset: 4 */
  275. /* End: */