file.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:12k
- /*****************************************************************************
- * file.c : audio output which writes the samples to a file
- *****************************************************************************
- * Copyright (C) 2002 VideoLAN
- * $Id: file.c 7522 2004-04-27 16:35:15Z sam $
- *
- * Authors: Christophe Massiot <massiot@via.ecp.fr>
- * Gildas Bazin <gbazin@netcourrier.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
- *****************************************************************************/
- /*****************************************************************************
- * Preamble
- *****************************************************************************/
- #include <string.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <vlc/vlc.h>
- #include <vlc/aout.h>
- #include "aout_internal.h"
- #include "codecs.h"
- #define FRAME_SIZE 2048
- #define A52_FRAME_NB 1536
- /*****************************************************************************
- * aout_sys_t: audio output method descriptor
- *****************************************************************************
- * This structure is part of the audio output thread descriptor.
- * It describes the direct sound specific properties of an audio device.
- *****************************************************************************/
- struct aout_sys_t
- {
- FILE * p_file;
- vlc_bool_t b_add_wav_header;
- WAVEHEADER waveh; /* Wave header of the output file */
- };
- #define CHANNELS_MAX 6
- static int pi_channels_maps[CHANNELS_MAX+1] =
- {
- 0,
- AOUT_CHAN_CENTER,
- AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
- AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
- AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
- | AOUT_CHAN_REARRIGHT,
- AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
- | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
- AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
- | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE
- };
- /*****************************************************************************
- * Local prototypes.
- *****************************************************************************/
- static int Open ( vlc_object_t * );
- static void Close ( vlc_object_t * );
- static void Play ( aout_instance_t * );
- /*****************************************************************************
- * Module descriptor
- *****************************************************************************/
- #define FORMAT_TEXT N_("Output format")
- #define FORMAT_LONGTEXT N_("One of "u8", "s8", "u16", "s16", "
- ""u16_le", "s16_le", "u16_be", "s16_be", "fixed32", "
- ""float32" or "spdif"")
- #define CHANNELS_TEXT N_("Output channels number")
- #define CHANNELS_LONGTEXT N_("By default, all the channels of the incoming "
- "will be saved but you can restrict the number of channels here.")
- #define WAV_TEXT N_("Add wave header")
- #define WAV_LONGTEXT N_("Instead of writing a raw file, you can add a WAV "
- "header to the file")
- static char *format_list[] = { "u8", "s8", "u16", "s16", "u16_le", "s16_le",
- "u16_be", "s16_be", "fixed32", "float32",
- "spdif" };
- static int format_int[] = { VLC_FOURCC('u','8',' ',' '),
- VLC_FOURCC('s','8',' ',' '),
- AOUT_FMT_U16_NE, AOUT_FMT_S16_NE,
- VLC_FOURCC('u','1','6','l'),
- VLC_FOURCC('s','1','6','l'),
- VLC_FOURCC('u','1','6','b'),
- VLC_FOURCC('s','1','6','b'),
- VLC_FOURCC('f','i','3','2'),
- VLC_FOURCC('f','l','3','2'),
- VLC_FOURCC('s','p','i','f') };
- #define FILE_TEXT N_("Output file")
- #define FILE_LONGTEXT N_("File to which the audio samples will be written to")
- vlc_module_begin();
- set_description( N_("File audio output") );
- add_string( "audiofile-format", "s16", NULL,
- FORMAT_TEXT, FORMAT_LONGTEXT, VLC_TRUE );
- change_string_list( format_list, 0, 0 );
- add_integer( "audiofile-channels", 0, NULL,
- CHANNELS_TEXT, CHANNELS_LONGTEXT, VLC_TRUE );
- add_file( "audiofile-file", "audiofile.wav", NULL, FILE_TEXT,
- FILE_LONGTEXT, VLC_FALSE );
- add_bool( "audiofile-wav", 1, NULL, WAV_TEXT, WAV_LONGTEXT, VLC_TRUE );
- set_capability( "audio output", 0 );
- add_shortcut( "file" );
- add_shortcut( "audiofile" );
- set_callbacks( Open, Close );
- vlc_module_end();
- /*****************************************************************************
- * Open: open a dummy audio device
- *****************************************************************************/
- static int Open( vlc_object_t * p_this )
- {
- aout_instance_t * p_aout = (aout_instance_t *)p_this;
- char * psz_name, * psz_format;
- char ** ppsz_compare = format_list;
- vlc_value_t val;
- int i_channels, i = 0;
- var_Create( p_this, "audiofile-file", VLC_VAR_STRING|VLC_VAR_DOINHERIT );
- var_Get( p_this, "audiofile-file", &val );
- psz_name = val.psz_string;
- if( !psz_name || !*psz_name )
- {
- msg_Err( p_aout, "you need to specify an output file name" );
- if( psz_name ) free( psz_name );
- return VLC_EGENERIC;
- }
- /* Allocate structure */
- p_aout->output.p_sys = malloc( sizeof( aout_sys_t ) );
- if( p_aout->output.p_sys == NULL )
- {
- msg_Err( p_aout, "out of memory" );
- return VLC_EGENERIC;
- }
- p_aout->output.p_sys->p_file = fopen( psz_name, "wb" );
- free( psz_name );
- if ( p_aout->output.p_sys->p_file == NULL )
- {
- free( p_aout->output.p_sys );
- return VLC_EGENERIC;
- }
- p_aout->output.pf_play = Play;
- /* Audio format */
- var_Create( p_this, "audiofile-format", VLC_VAR_STRING|VLC_VAR_DOINHERIT );
- var_Get( p_this, "audiofile-format", &val );
- psz_format = val.psz_string;
- while ( *ppsz_compare != NULL )
- {
- if ( !strncmp( *ppsz_compare, psz_format, strlen(*ppsz_compare) ) )
- {
- break;
- }
- ppsz_compare++; i++;
- }
- if ( *ppsz_compare == NULL )
- {
- msg_Err( p_aout, "cannot understand the format string (%s)",
- psz_format );
- fclose( p_aout->output.p_sys->p_file );
- free( p_aout->output.p_sys );
- return VLC_EGENERIC;
- }
- p_aout->output.output.i_format = format_int[i];
- if ( AOUT_FMT_NON_LINEAR( &p_aout->output.output ) )
- {
- p_aout->output.i_nb_samples = A52_FRAME_NB;
- p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE;
- p_aout->output.output.i_frame_length = A52_FRAME_NB;
- aout_VolumeNoneInit( p_aout );
- }
- else
- {
- p_aout->output.i_nb_samples = FRAME_SIZE;
- aout_VolumeSoftInit( p_aout );
- }
- /* Channels number */
- var_Create( p_this, "audiofile-channels",
- VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
- var_Get( p_this, "audiofile-channels", &val );
- i_channels = val.i_int;
- if( i_channels > 0 && i_channels <= CHANNELS_MAX )
- {
- p_aout->output.output.i_physical_channels =
- pi_channels_maps[i_channels];
- }
- /* WAV header */
- var_Create( p_this, "audiofile-wav", VLC_VAR_BOOL|VLC_VAR_DOINHERIT );
- var_Get( p_this, "audiofile-wav", &val );
- p_aout->output.p_sys->b_add_wav_header = val.b_bool;
- if( p_aout->output.p_sys->b_add_wav_header )
- {
- /* Write wave header */
- WAVEHEADER *wh = &p_aout->output.p_sys->waveh;
- memset( wh, 0, sizeof(wh) );
- switch( p_aout->output.output.i_format )
- {
- case VLC_FOURCC('f','l','3','2'):
- wh->Format = WAVE_FORMAT_IEEE_FLOAT;
- wh->BitsPerSample = sizeof(float) * 8;
- break;
- case VLC_FOURCC('u','8',' ',' '):
- wh->Format = WAVE_FORMAT_PCM;
- wh->BitsPerSample = 8;
- break;
- case VLC_FOURCC('s','1','6','l'):
- default:
- wh->Format = WAVE_FORMAT_PCM;
- wh->BitsPerSample = 16;
- break;
- }
- wh->MainChunkID = VLC_FOURCC('R', 'I', 'F', 'F');
- wh->Length = 0; /* temp, to be filled in as we go */
- wh->ChunkTypeID = VLC_FOURCC('W', 'A', 'V', 'E');
- wh->SubChunkID = VLC_FOURCC('f', 'm', 't', ' ');
- wh->SubChunkLength = 16;
- wh->Modus = aout_FormatNbChannels( &p_aout->output.output );
- wh->SampleFreq = p_aout->output.output.i_rate;
- wh->BytesPerSample = wh->Modus * ( wh->BitsPerSample / 8 );
- wh->BytesPerSec = wh->BytesPerSample * wh->SampleFreq;
- wh->DataChunkID = VLC_FOURCC('d', 'a', 't', 'a');
- wh->DataLength = 0; /* temp, to be filled in as we go */
- /* Header -> little endian format */
- SetWLE( &wh->Format, wh->Format );
- SetWLE( &wh->BitsPerSample, wh->BitsPerSample );
- SetDWLE( &wh->SubChunkLength, wh->SubChunkLength );
- SetWLE( &wh->Modus, wh->Modus );
- SetDWLE( &wh->SampleFreq, wh->SampleFreq );
- SetWLE( &wh->BytesPerSample, wh->BytesPerSample );
- SetDWLE( &wh->BytesPerSec, wh->BytesPerSec );
- if( fwrite( wh, sizeof(WAVEHEADER), 1,
- p_aout->output.p_sys->p_file ) != 1 )
- {
- msg_Err( p_aout, "write error (%s)", strerror(errno) );
- }
- }
- return 0;
- }
- /*****************************************************************************
- * Close: close our file
- *****************************************************************************/
- static void Close( vlc_object_t * p_this )
- {
- aout_instance_t * p_aout = (aout_instance_t *)p_this;
- msg_Dbg( p_aout, "closing audio file" );
- if( p_aout->output.p_sys->b_add_wav_header )
- {
- /* Update Wave Header */
- p_aout->output.p_sys->waveh.Length =
- p_aout->output.p_sys->waveh.DataLength + sizeof(WAVEHEADER) - 4;
- /* Write Wave Header */
- if( fseek( p_aout->output.p_sys->p_file, 0, SEEK_SET ) )
- {
- msg_Err( p_aout, "seek error (%s)", strerror(errno) );
- }
- /* Header -> little endian format */
- SetDWLE( &p_aout->output.p_sys->waveh.Length,
- p_aout->output.p_sys->waveh.Length );
- SetDWLE( &p_aout->output.p_sys->waveh.DataLength,
- p_aout->output.p_sys->waveh.DataLength );
- if( fwrite( &p_aout->output.p_sys->waveh, sizeof(WAVEHEADER), 1,
- p_aout->output.p_sys->p_file ) != 1 )
- {
- msg_Err( p_aout, "write error (%s)", strerror(errno) );
- }
- }
- fclose( p_aout->output.p_sys->p_file );
- free( p_aout->output.p_sys );
- }
- /*****************************************************************************
- * Play: pretend to play a sound
- *****************************************************************************/
- static void Play( aout_instance_t * p_aout )
- {
- aout_buffer_t * p_buffer;
- p_buffer = aout_FifoPop( p_aout, &p_aout->output.fifo );
- if( fwrite( p_buffer->p_buffer, p_buffer->i_nb_bytes, 1,
- p_aout->output.p_sys->p_file ) != 1 )
- {
- msg_Err( p_aout, "write error (%s)", strerror(errno) );
- }
- if( p_aout->output.p_sys->b_add_wav_header )
- {
- /* Update Wave Header */
- p_aout->output.p_sys->waveh.DataLength += p_buffer->i_nb_bytes;
- }
- aout_BufferFree( p_buffer );
- }