file.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:12k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * file.c : audio output which writes the samples to a file
  3.  *****************************************************************************
  4.  * Copyright (C) 2002 VideoLAN
  5.  * $Id: file.c 7522 2004-04-27 16:35:15Z sam $
  6.  *
  7.  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  8.  *          Gildas Bazin <gbazin@netcourrier.com>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  23.  *****************************************************************************/
  24. /*****************************************************************************
  25.  * Preamble
  26.  *****************************************************************************/
  27. #include <string.h>
  28. #include <stdlib.h>
  29. #include <errno.h>
  30. #include <vlc/vlc.h>
  31. #include <vlc/aout.h>
  32. #include "aout_internal.h"
  33. #include "codecs.h"
  34. #define FRAME_SIZE 2048
  35. #define A52_FRAME_NB 1536
  36. /*****************************************************************************
  37.  * aout_sys_t: audio output method descriptor
  38.  *****************************************************************************
  39.  * This structure is part of the audio output thread descriptor.
  40.  * It describes the direct sound specific properties of an audio device.
  41.  *****************************************************************************/
  42. struct aout_sys_t
  43. {
  44.     FILE     * p_file;
  45.     vlc_bool_t b_add_wav_header;
  46.     WAVEHEADER waveh;                      /* Wave header of the output file */
  47. };
  48. #define CHANNELS_MAX 6
  49. static int pi_channels_maps[CHANNELS_MAX+1] =
  50. {
  51.     0,
  52.     AOUT_CHAN_CENTER,
  53.     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
  54.     AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
  55.     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
  56.      | AOUT_CHAN_REARRIGHT,
  57.     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
  58.      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
  59.     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
  60.      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE
  61. };
  62. /*****************************************************************************
  63.  * Local prototypes.
  64.  *****************************************************************************/
  65. static int     Open        ( vlc_object_t * );
  66. static void    Close       ( vlc_object_t * );
  67. static void    Play        ( aout_instance_t * );
  68. /*****************************************************************************
  69.  * Module descriptor
  70.  *****************************************************************************/
  71. #define FORMAT_TEXT N_("Output format")
  72. #define FORMAT_LONGTEXT N_("One of "u8", "s8", "u16", "s16", " 
  73.     ""u16_le", "s16_le", "u16_be", "s16_be", "fixed32", " 
  74.     ""float32" or "spdif"")
  75. #define CHANNELS_TEXT N_("Output channels number")
  76. #define CHANNELS_LONGTEXT N_("By default, all the channels of the incoming " 
  77.     "will be saved but you can restrict the number of channels here.")
  78. #define WAV_TEXT N_("Add wave header")
  79. #define WAV_LONGTEXT N_("Instead of writing a raw file, you can add a WAV " 
  80.                         "header to the file")
  81. static char *format_list[] = { "u8", "s8", "u16", "s16", "u16_le", "s16_le",
  82.                                "u16_be", "s16_be", "fixed32", "float32",
  83.                                "spdif" };
  84. static int format_int[] = { VLC_FOURCC('u','8',' ',' '),
  85.                             VLC_FOURCC('s','8',' ',' '),
  86.                             AOUT_FMT_U16_NE, AOUT_FMT_S16_NE,
  87.                             VLC_FOURCC('u','1','6','l'),
  88.                             VLC_FOURCC('s','1','6','l'),
  89.                             VLC_FOURCC('u','1','6','b'),
  90.                             VLC_FOURCC('s','1','6','b'),
  91.                             VLC_FOURCC('f','i','3','2'),
  92.                             VLC_FOURCC('f','l','3','2'),
  93.                             VLC_FOURCC('s','p','i','f') };
  94. #define FILE_TEXT N_("Output file")
  95. #define FILE_LONGTEXT N_("File to which the audio samples will be written to")
  96. vlc_module_begin();
  97.     set_description( N_("File audio output") );
  98.     add_string( "audiofile-format", "s16", NULL,
  99.                 FORMAT_TEXT, FORMAT_LONGTEXT, VLC_TRUE );
  100.         change_string_list( format_list, 0, 0 );
  101.     add_integer( "audiofile-channels", 0, NULL,
  102.                  CHANNELS_TEXT, CHANNELS_LONGTEXT, VLC_TRUE );
  103.     add_file( "audiofile-file", "audiofile.wav", NULL, FILE_TEXT,
  104.               FILE_LONGTEXT, VLC_FALSE );
  105.     add_bool( "audiofile-wav", 1, NULL, WAV_TEXT, WAV_LONGTEXT, VLC_TRUE );
  106.     set_capability( "audio output", 0 );
  107.     add_shortcut( "file" );
  108.     add_shortcut( "audiofile" );
  109.     set_callbacks( Open, Close );
  110. vlc_module_end();
  111. /*****************************************************************************
  112.  * Open: open a dummy audio device
  113.  *****************************************************************************/
  114. static int Open( vlc_object_t * p_this )
  115. {
  116.     aout_instance_t * p_aout = (aout_instance_t *)p_this;
  117.     char * psz_name, * psz_format;
  118.     char ** ppsz_compare = format_list;
  119.     vlc_value_t val;
  120.     int i_channels, i = 0;
  121.     var_Create( p_this, "audiofile-file", VLC_VAR_STRING|VLC_VAR_DOINHERIT );
  122.     var_Get( p_this, "audiofile-file", &val );
  123.     psz_name = val.psz_string;
  124.     if( !psz_name || !*psz_name )
  125.     {
  126.         msg_Err( p_aout, "you need to specify an output file name" );
  127.         if( psz_name ) free( psz_name );
  128.         return VLC_EGENERIC;
  129.     }
  130.     /* Allocate structure */
  131.     p_aout->output.p_sys = malloc( sizeof( aout_sys_t ) );
  132.     if( p_aout->output.p_sys == NULL )
  133.     {
  134.         msg_Err( p_aout, "out of memory" );
  135.         return VLC_EGENERIC;
  136.     }
  137.     p_aout->output.p_sys->p_file = fopen( psz_name, "wb" );
  138.     free( psz_name );
  139.     if ( p_aout->output.p_sys->p_file == NULL )
  140.     {
  141.         free( p_aout->output.p_sys );
  142.         return VLC_EGENERIC;
  143.     }
  144.     p_aout->output.pf_play = Play;
  145.     /* Audio format */
  146.     var_Create( p_this, "audiofile-format", VLC_VAR_STRING|VLC_VAR_DOINHERIT );
  147.     var_Get( p_this, "audiofile-format", &val );
  148.     psz_format = val.psz_string;
  149.     while ( *ppsz_compare != NULL )
  150.     {
  151.         if ( !strncmp( *ppsz_compare, psz_format, strlen(*ppsz_compare) ) )
  152.         {
  153.             break;
  154.         }
  155.         ppsz_compare++; i++;
  156.     }
  157.     if ( *ppsz_compare == NULL )
  158.     {
  159.         msg_Err( p_aout, "cannot understand the format string (%s)",
  160.                  psz_format );
  161.         fclose( p_aout->output.p_sys->p_file );
  162.         free( p_aout->output.p_sys );
  163.         return VLC_EGENERIC;
  164.     }
  165.     p_aout->output.output.i_format = format_int[i];
  166.     if ( AOUT_FMT_NON_LINEAR( &p_aout->output.output ) )
  167.     {
  168.         p_aout->output.i_nb_samples = A52_FRAME_NB;
  169.         p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE;
  170.         p_aout->output.output.i_frame_length = A52_FRAME_NB;
  171.         aout_VolumeNoneInit( p_aout );
  172.     }
  173.     else
  174.     {
  175.         p_aout->output.i_nb_samples = FRAME_SIZE;
  176.         aout_VolumeSoftInit( p_aout );
  177.     }
  178.     /* Channels number */
  179.     var_Create( p_this, "audiofile-channels",
  180.                 VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
  181.     var_Get( p_this, "audiofile-channels", &val );
  182.     i_channels = val.i_int;
  183.     if( i_channels > 0 && i_channels <= CHANNELS_MAX )
  184.     {
  185.         p_aout->output.output.i_physical_channels =
  186.             pi_channels_maps[i_channels];
  187.     }
  188.     /* WAV header */
  189.     var_Create( p_this, "audiofile-wav", VLC_VAR_BOOL|VLC_VAR_DOINHERIT );
  190.     var_Get( p_this, "audiofile-wav", &val );
  191.     p_aout->output.p_sys->b_add_wav_header = val.b_bool;
  192.     if( p_aout->output.p_sys->b_add_wav_header )
  193.     {
  194.         /* Write wave header */
  195.         WAVEHEADER *wh = &p_aout->output.p_sys->waveh;
  196.         memset( wh, 0, sizeof(wh) );
  197.         switch( p_aout->output.output.i_format )
  198.         {
  199.         case VLC_FOURCC('f','l','3','2'):
  200.             wh->Format     = WAVE_FORMAT_IEEE_FLOAT;
  201.             wh->BitsPerSample = sizeof(float) * 8;
  202.             break;
  203.         case VLC_FOURCC('u','8',' ',' '):
  204.             wh->Format     = WAVE_FORMAT_PCM;
  205.             wh->BitsPerSample = 8;
  206.             break;
  207.         case VLC_FOURCC('s','1','6','l'):
  208.         default:
  209.             wh->Format     = WAVE_FORMAT_PCM;
  210.             wh->BitsPerSample = 16;
  211.             break;
  212.         }
  213.         wh->MainChunkID = VLC_FOURCC('R', 'I', 'F', 'F');
  214.         wh->Length = 0;                    /* temp, to be filled in as we go */
  215.         wh->ChunkTypeID = VLC_FOURCC('W', 'A', 'V', 'E');
  216.         wh->SubChunkID = VLC_FOURCC('f', 'm', 't', ' ');
  217.         wh->SubChunkLength = 16;
  218.         wh->Modus = aout_FormatNbChannels( &p_aout->output.output );
  219.         wh->SampleFreq = p_aout->output.output.i_rate;
  220.         wh->BytesPerSample = wh->Modus * ( wh->BitsPerSample / 8 );
  221.         wh->BytesPerSec = wh->BytesPerSample * wh->SampleFreq;
  222.         wh->DataChunkID = VLC_FOURCC('d', 'a', 't', 'a');
  223.         wh->DataLength = 0;                /* temp, to be filled in as we go */
  224.         /* Header -> little endian format */
  225.         SetWLE( &wh->Format, wh->Format );
  226.         SetWLE( &wh->BitsPerSample, wh->BitsPerSample );
  227.         SetDWLE( &wh->SubChunkLength, wh->SubChunkLength );
  228.         SetWLE( &wh->Modus, wh->Modus );
  229.         SetDWLE( &wh->SampleFreq, wh->SampleFreq );
  230.         SetWLE( &wh->BytesPerSample, wh->BytesPerSample );
  231.         SetDWLE( &wh->BytesPerSec, wh->BytesPerSec );
  232.         if( fwrite( wh, sizeof(WAVEHEADER), 1,
  233.                     p_aout->output.p_sys->p_file ) != 1 )
  234.         {
  235.             msg_Err( p_aout, "write error (%s)", strerror(errno) );
  236.         }
  237.     }
  238.     return 0;
  239. }
  240. /*****************************************************************************
  241.  * Close: close our file
  242.  *****************************************************************************/
  243. static void Close( vlc_object_t * p_this )
  244. {
  245.     aout_instance_t * p_aout = (aout_instance_t *)p_this;
  246.     msg_Dbg( p_aout, "closing audio file" );
  247.     if( p_aout->output.p_sys->b_add_wav_header )
  248.     {
  249.         /* Update Wave Header */
  250.         p_aout->output.p_sys->waveh.Length =
  251.             p_aout->output.p_sys->waveh.DataLength + sizeof(WAVEHEADER) - 4;
  252.         /* Write Wave Header */
  253.         if( fseek( p_aout->output.p_sys->p_file, 0, SEEK_SET ) )
  254.         {
  255.             msg_Err( p_aout, "seek error (%s)", strerror(errno) );
  256.         }
  257.         /* Header -> little endian format */
  258.         SetDWLE( &p_aout->output.p_sys->waveh.Length,
  259.                  p_aout->output.p_sys->waveh.Length );
  260.         SetDWLE( &p_aout->output.p_sys->waveh.DataLength,
  261.                  p_aout->output.p_sys->waveh.DataLength );
  262.         if( fwrite( &p_aout->output.p_sys->waveh, sizeof(WAVEHEADER), 1,
  263.                     p_aout->output.p_sys->p_file ) != 1 )
  264.         {
  265.             msg_Err( p_aout, "write error (%s)", strerror(errno) );
  266.         }
  267.     }
  268.     fclose( p_aout->output.p_sys->p_file );
  269.     free( p_aout->output.p_sys );
  270. }
  271. /*****************************************************************************
  272.  * Play: pretend to play a sound
  273.  *****************************************************************************/
  274. static void Play( aout_instance_t * p_aout )
  275. {
  276.     aout_buffer_t * p_buffer;
  277.     p_buffer = aout_FifoPop( p_aout, &p_aout->output.fifo );
  278.     if( fwrite( p_buffer->p_buffer, p_buffer->i_nb_bytes, 1,
  279.                 p_aout->output.p_sys->p_file ) != 1 )
  280.     {
  281.         msg_Err( p_aout, "write error (%s)", strerror(errno) );
  282.     }
  283.     if( p_aout->output.p_sys->b_add_wav_header )
  284.     {
  285.         /* Update Wave Header */
  286.         p_aout->output.p_sys->waveh.DataLength += p_buffer->i_nb_bytes;
  287.     }
  288.     aout_BufferFree( p_buffer );
  289. }