?? input.c
字號:
/***************************************************************************** * input.c : internal management of input streams for the audio output ***************************************************************************** * Copyright (C) 2002-2004 VideoLAN * $Id: input.c 11112 2005-05-22 16:18:46Z zorglub $ * * Authors: Christophe Massiot <massiot@via.ecp.fr> * * 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 <stdlib.h> /* calloc(), malloc(), free() */#include <string.h>#include <vlc/vlc.h>#include <vlc/input.h> /* for input_thread_t and i_pts_delay */#ifdef HAVE_ALLOCA_H# include <alloca.h>#endif#include "audio_output.h"#include "aout_internal.h"static int VisualizationCallback( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * );static int EqualizerCallback( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * );static aout_filter_t * allocateUserChannelMixer( aout_instance_t *, audio_sample_format_t *, audio_sample_format_t * );/***************************************************************************** * aout_InputNew : allocate a new input and rework the filter pipeline *****************************************************************************/int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input ){ audio_sample_format_t user_filter_format; audio_sample_format_t intermediate_format;/* input of resampler */ vlc_value_t val, text; char * psz_filters, *psz_visual; aout_filter_t * p_user_channel_mixer; aout_FormatPrint( p_aout, "input", &p_input->input ); /* Prepare FIFO. */ aout_FifoInit( p_aout, &p_input->fifo, p_aout->mixer.mixer.i_rate ); p_input->p_first_byte_to_mix = NULL; /* Prepare format structure */ memcpy( &intermediate_format, &p_aout->mixer.mixer, sizeof(audio_sample_format_t) ); intermediate_format.i_rate = p_input->input.i_rate; /* Try to use the channel mixer chosen by the user */ memcpy ( &user_filter_format, &intermediate_format, sizeof(audio_sample_format_t) ); user_filter_format.i_physical_channels = p_input->input.i_physical_channels; user_filter_format.i_original_channels = p_input->input.i_original_channels; user_filter_format.i_bytes_per_frame = user_filter_format.i_bytes_per_frame * aout_FormatNbChannels( &user_filter_format ) / aout_FormatNbChannels( &intermediate_format ); p_user_channel_mixer = allocateUserChannelMixer( p_aout, &user_filter_format, &intermediate_format ); /* If it failed, let the main pipeline do channel mixing */ if ( ! p_user_channel_mixer ) { memcpy ( &user_filter_format, &intermediate_format, sizeof(audio_sample_format_t) ); } /* Create filters. */ if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_filters, &p_input->i_nb_filters, &p_input->input, &user_filter_format ) < 0 ) { msg_Err( p_aout, "couldn't set an input pipeline" ); aout_FifoDestroy( p_aout, &p_input->fifo ); p_input->b_error = 1; return -1; } /* Now add user filters */ if( var_Type( p_aout, "visual" ) == 0 ) { module_t *p_module; var_Create( p_aout, "visual", VLC_VAR_STRING | VLC_VAR_HASCHOICE ); text.psz_string = _("Visualizations"); var_Change( p_aout, "visual", VLC_VAR_SETTEXT, &text, NULL ); val.psz_string = ""; text.psz_string = _("Disable"); var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text ); val.psz_string = "random"; text.psz_string = _("Random"); var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text ); val.psz_string = "scope"; text.psz_string = _("Scope"); var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text ); val.psz_string = "spectrum"; text.psz_string = _("Spectrum"); var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text ); /* Look for goom plugin */ p_module = config_FindModule( VLC_OBJECT(p_aout), "goom" ); if( p_module ) { val.psz_string = "goom"; text.psz_string = "Goom"; var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text ); } /* Look for galaktos plugin */ p_module = config_FindModule( VLC_OBJECT(p_aout), "galaktos" ); if( p_module ) { val.psz_string = "galaktos"; text.psz_string = "GaLaktos"; var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text ); } if( var_Get( p_aout, "effect-list", &val ) == VLC_SUCCESS ) { var_Set( p_aout, "visual", val ); if( val.psz_string ) free( val.psz_string ); } var_AddCallback( p_aout, "visual", VisualizationCallback, NULL ); } if( var_Type( p_aout, "equalizer" ) == 0 ) { module_config_t *p_config; int i; p_config = config_FindConfig( VLC_OBJECT(p_aout), "equalizer-preset" ); if( p_config && p_config->i_list ) { var_Create( p_aout, "equalizer", VLC_VAR_STRING | VLC_VAR_HASCHOICE ); text.psz_string = _("Equalizer"); var_Change( p_aout, "equalizer", VLC_VAR_SETTEXT, &text, NULL ); val.psz_string = ""; text.psz_string = _("Disable"); var_Change( p_aout, "equalizer", VLC_VAR_ADDCHOICE, &val, &text ); for( i = 0; i < p_config->i_list; i++ ) { val.psz_string = p_config->ppsz_list[i]; text.psz_string = p_config->ppsz_list_text[i]; var_Change( p_aout, "equalizer", VLC_VAR_ADDCHOICE, &val, &text ); } var_AddCallback( p_aout, "equalizer", EqualizerCallback, NULL ); } } if( var_Type( p_aout, "audio-filter" ) == 0 ) { var_Create( p_aout, "audio-filter", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); text.psz_string = _("Audio filters"); var_Change( p_aout, "audio-filter", VLC_VAR_SETTEXT, &text, NULL ); } if( var_Type( p_aout, "audio-visual" ) == 0 ) { var_Create( p_aout, "audio-visual", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); text.psz_string = _("Audio visualizations"); var_Change( p_aout, "audio-visual", VLC_VAR_SETTEXT, &text, NULL ); } var_Get( p_aout, "audio-filter", &val ); psz_filters = val.psz_string; var_Get( p_aout, "audio-visual", &val ); psz_visual = val.psz_string; if( psz_filters && *psz_filters && psz_visual && *psz_visual ) { psz_filters = (char *)realloc( psz_filters, strlen( psz_filters ) + strlen( psz_visual ) + 1); sprintf( psz_filters, "%s:%s", psz_filters, psz_visual ); } else if( psz_visual && *psz_visual ) { if( psz_filters ) free( psz_filters ); psz_filters = strdup( psz_visual ); } if( psz_filters && *psz_filters ) { char *psz_parser = psz_filters; char *psz_next; if( strchr( psz_filters, ',' ) && !strchr( psz_filters, ':' ) ) { msg_Info( p_aout, "Warning: you are using a deprecated syntax for " "audio-filter / audio-visual." ); msg_Info( p_aout, "You must now use ':' as separator instead of " "','." ); } while( psz_parser && *psz_parser ) { aout_filter_t * p_filter; if( p_input->i_nb_filters >= AOUT_MAX_FILTERS ) { msg_Dbg( p_aout, "max filter reached (%d)", AOUT_MAX_FILTERS ); break; } while( *psz_parser == ' ' || *psz_parser == ':' || *psz_parser == ',') { psz_parser++; } if( ( psz_next = strchr( psz_parser , ':' ) ) ) { *psz_next++ = '\0'; } else if( ( psz_next = strchr( psz_parser , ',' ) ) ) { *psz_next++ = '\0'; } if( *psz_parser =='\0' ) { break; } msg_Dbg( p_aout, "user filter \"%s\"", psz_parser ); /* Create a VLC object */ p_filter = vlc_object_create( p_aout, sizeof(aout_filter_t) ); if( p_filter == NULL ) { msg_Err( p_aout, "cannot add user filter %s (skipped)", psz_parser ); psz_parser = psz_next; continue; } vlc_object_attach( p_filter , p_aout ); memcpy( &p_filter->input, &user_filter_format, sizeof(audio_sample_format_t) ); memcpy( &p_filter->output, &user_filter_format, sizeof(audio_sample_format_t) ); p_filter->p_module = module_Need( p_filter,"audio filter", psz_parser, VLC_FALSE ); if( p_filter->p_module== NULL ) { p_filter->p_module = module_Need( p_filter,"visualization", psz_parser, VLC_FALSE ); if( p_filter->p_module == NULL ) { msg_Err( p_aout, "cannot add user filter %s (skipped)", psz_parser ); vlc_object_detach( p_filter ); vlc_object_destroy( p_filter ); psz_parser = psz_next; continue; } } p_filter->b_continuity = VLC_FALSE; p_input->pp_filters[p_input->i_nb_filters++] = p_filter; /* next filter if any */ psz_parser = psz_next; } } if( psz_filters ) free( psz_filters ); if( psz_visual ) free( psz_visual ); /* Attach the user channel mixer */ if ( p_user_channel_mixer ) { p_input->pp_filters[p_input->i_nb_filters++] = p_user_channel_mixer; } /* Prepare hints for the buffer allocator. */ p_input->input_alloc.i_alloc_type = AOUT_ALLOC_HEAP; p_input->input_alloc.i_bytes_per_sec = -1; if ( AOUT_FMT_NON_LINEAR( &p_aout->mixer.mixer ) ) { p_input->i_nb_resamplers = 0; } else { /* Create resamplers. */ intermediate_format.i_rate = (__MAX(p_input->input.i_rate, p_aout->mixer.mixer.i_rate) * (100 + AOUT_MAX_RESAMPLING)) / 100; if ( intermediate_format.i_rate == p_aout->mixer.mixer.i_rate ) { /* Just in case... */ intermediate_format.i_rate++; } if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_resamplers, &p_input->i_nb_resamplers, &intermediate_format, &p_aout->mixer.mixer ) < 0 ) { msg_Err( p_aout, "couldn't set a resampler pipeline" ); aout_FiltersDestroyPipeline( p_aout, p_input->pp_filters, p_input->i_nb_filters ); aout_FifoDestroy( p_aout, &p_input->fifo ); var_Destroy( p_aout, "visual" ); p_input->b_error = 1; return -1; } aout_FiltersHintBuffers( p_aout, p_input->pp_resamplers, p_input->i_nb_resamplers, &p_input->input_alloc ); /* Setup the initial rate of the resampler */ p_input->pp_resamplers[0]->input.i_rate = p_input->input.i_rate; } p_input->i_resampling_type = AOUT_RESAMPLING_NONE; p_input->input_alloc.i_alloc_type = AOUT_ALLOC_HEAP; aout_FiltersHintBuffers( p_aout, p_input->pp_filters, p_input->i_nb_filters, &p_input->input_alloc ); /* i_bytes_per_sec is still == -1 if no filters */ p_input->input_alloc.i_bytes_per_sec = __MAX( p_input->input_alloc.i_bytes_per_sec, (int)(p_input->input.i_bytes_per_frame * p_input->input.i_rate / p_input->input.i_frame_length) ); /* Allocate in the heap, it is more convenient for the decoder. */ p_input->input_alloc.i_alloc_type = AOUT_ALLOC_HEAP; p_input->b_error = VLC_FALSE; p_input->b_restart = VLC_FALSE; return 0;}/***************************************************************************** * aout_InputDelete : delete an input ***************************************************************************** * This function must be entered with the mixer lock. *****************************************************************************/int aout_InputDelete( aout_instance_t * p_aout, aout_input_t * p_input ){ if ( p_input->b_error ) return 0; aout_FiltersDestroyPipeline( p_aout, p_input->pp_filters, p_input->i_nb_filters ); aout_FiltersDestroyPipeline( p_aout, p_input->pp_resamplers, p_input->i_nb_resamplers ); aout_FifoDestroy( p_aout, &p_input->fifo ); return 0;}/***************************************************************************** * aout_InputPlay : play a buffer ***************************************************************************** * This function must be entered with the input lock. *****************************************************************************/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -