?? input.c
字號:
int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input, aout_buffer_t * p_buffer ){ mtime_t start_date; if( p_input->b_restart ) { aout_fifo_t fifo, dummy_fifo; byte_t *p_first_byte_to_mix; vlc_mutex_lock( &p_aout->mixer_lock ); /* A little trick to avoid loosing our input fifo */ aout_FifoInit( p_aout, &dummy_fifo, p_aout->mixer.mixer.i_rate ); p_first_byte_to_mix = p_input->p_first_byte_to_mix; fifo = p_input->fifo; p_input->fifo = dummy_fifo; aout_InputDelete( p_aout, p_input ); aout_InputNew( p_aout, p_input ); p_input->p_first_byte_to_mix = p_first_byte_to_mix; p_input->fifo = fifo; vlc_mutex_unlock( &p_aout->mixer_lock ); } /* We don't care if someone changes the start date behind our back after * this. We'll deal with that when pushing the buffer, and compensate * with the next incoming buffer. */ vlc_mutex_lock( &p_aout->input_fifos_lock ); start_date = aout_FifoNextStart( p_aout, &p_input->fifo ); vlc_mutex_unlock( &p_aout->input_fifos_lock ); if ( start_date != 0 && start_date < mdate() ) { /* The decoder is _very_ late. This can only happen if the user * pauses the stream (or if the decoder is buggy, which cannot * happen :). */ msg_Warn( p_aout, "computed PTS is out of range ("I64Fd"), " "clearing out", mdate() - start_date ); vlc_mutex_lock( &p_aout->input_fifos_lock ); aout_FifoSet( p_aout, &p_input->fifo, 0 ); p_input->p_first_byte_to_mix = NULL; vlc_mutex_unlock( &p_aout->input_fifos_lock ); if ( p_input->i_resampling_type != AOUT_RESAMPLING_NONE ) msg_Warn( p_aout, "timing screwed, stopping resampling" ); p_input->i_resampling_type = AOUT_RESAMPLING_NONE; if ( p_input->i_nb_resamplers != 0 ) { p_input->pp_resamplers[0]->input.i_rate = p_input->input.i_rate; p_input->pp_resamplers[0]->b_continuity = VLC_FALSE; } start_date = 0; } if ( p_buffer->start_date < mdate() + AOUT_MIN_PREPARE_TIME ) { /* The decoder gives us f*cked up PTS. It's its business, but we * can't present it anyway, so drop the buffer. */ msg_Warn( p_aout, "PTS is out of range ("I64Fd"), dropping buffer", mdate() - p_buffer->start_date ); aout_BufferFree( p_buffer ); p_input->i_resampling_type = AOUT_RESAMPLING_NONE; if ( p_input->i_nb_resamplers != 0 ) { p_input->pp_resamplers[0]->input.i_rate = p_input->input.i_rate; p_input->pp_resamplers[0]->b_continuity = VLC_FALSE; } return 0; } /* If the audio drift is too big then it's not worth trying to resample * the audio. */ if ( start_date != 0 && ( start_date < p_buffer->start_date - 3 * AOUT_PTS_TOLERANCE ) ) { msg_Warn( p_aout, "audio drift is too big ("I64Fd"), clearing out", start_date - p_buffer->start_date ); vlc_mutex_lock( &p_aout->input_fifos_lock ); aout_FifoSet( p_aout, &p_input->fifo, 0 ); p_input->p_first_byte_to_mix = NULL; vlc_mutex_unlock( &p_aout->input_fifos_lock ); if ( p_input->i_resampling_type != AOUT_RESAMPLING_NONE ) msg_Warn( p_aout, "timing screwed, stopping resampling" ); p_input->i_resampling_type = AOUT_RESAMPLING_NONE; if ( p_input->i_nb_resamplers != 0 ) { p_input->pp_resamplers[0]->input.i_rate = p_input->input.i_rate; p_input->pp_resamplers[0]->b_continuity = VLC_FALSE; } start_date = 0; } else if ( start_date != 0 && ( start_date > p_buffer->start_date + 3 * AOUT_PTS_TOLERANCE ) ) { msg_Warn( p_aout, "audio drift is too big ("I64Fd"), dropping buffer", start_date - p_buffer->start_date ); aout_BufferFree( p_buffer ); return 0; } if ( start_date == 0 ) start_date = p_buffer->start_date; /* Run pre-filters. */ aout_FiltersPlay( p_aout, p_input->pp_filters, p_input->i_nb_filters, &p_buffer ); /* Run the resampler if needed. * We first need to calculate the output rate of this resampler. */ if ( ( p_input->i_resampling_type == AOUT_RESAMPLING_NONE ) && ( start_date < p_buffer->start_date - AOUT_PTS_TOLERANCE || start_date > p_buffer->start_date + AOUT_PTS_TOLERANCE ) && p_input->i_nb_resamplers > 0 ) { /* Can happen in several circumstances : * 1. A problem at the input (clock drift) * 2. A small pause triggered by the user * 3. Some delay in the output stage, causing a loss of lip * synchronization * Solution : resample the buffer to avoid a scratch. */ mtime_t drift = p_buffer->start_date - start_date; p_input->i_resamp_start_date = mdate(); p_input->i_resamp_start_drift = (int)drift; if ( drift > 0 ) p_input->i_resampling_type = AOUT_RESAMPLING_DOWN; else p_input->i_resampling_type = AOUT_RESAMPLING_UP; msg_Warn( p_aout, "buffer is "I64Fd" %s, triggering %ssampling", drift > 0 ? drift : -drift, drift > 0 ? "in advance" : "late", drift > 0 ? "down" : "up"); } if ( p_input->i_resampling_type != AOUT_RESAMPLING_NONE ) { /* Resampling has been triggered previously (because of dates * mismatch). We want the resampling to happen progressively so * it isn't too audible to the listener. */ if( p_input->i_resampling_type == AOUT_RESAMPLING_UP ) { p_input->pp_resamplers[0]->input.i_rate += 2; /* Hz */ } else { p_input->pp_resamplers[0]->input.i_rate -= 2; /* Hz */ } /* Check if everything is back to normal, in which case we can stop the * resampling */ if( p_input->pp_resamplers[0]->input.i_rate == p_input->input.i_rate ) { p_input->i_resampling_type = AOUT_RESAMPLING_NONE; msg_Warn( p_aout, "resampling stopped after "I64Fi" usec " "(drift: "I64Fi")", mdate() - p_input->i_resamp_start_date, p_buffer->start_date - start_date); } else if( abs( (int)(p_buffer->start_date - start_date) ) < abs( p_input->i_resamp_start_drift ) / 2 ) { /* if we reduced the drift from half, then it is time to switch * back the resampling direction. */ if( p_input->i_resampling_type == AOUT_RESAMPLING_UP ) p_input->i_resampling_type = AOUT_RESAMPLING_DOWN; else p_input->i_resampling_type = AOUT_RESAMPLING_UP; p_input->i_resamp_start_drift = 0; } else if( p_input->i_resamp_start_drift && ( abs( (int)(p_buffer->start_date - start_date) ) > abs( p_input->i_resamp_start_drift ) * 3 / 2 ) ) { /* If the drift is increasing and not decreasing, than something * is bad. We'd better stop the resampling right now. */ msg_Warn( p_aout, "timing screwed, stopping resampling" ); p_input->i_resampling_type = AOUT_RESAMPLING_NONE; p_input->pp_resamplers[0]->input.i_rate = p_input->input.i_rate; } } /* Adding the start date will be managed by aout_FifoPush(). */ p_buffer->end_date = start_date + (p_buffer->end_date - p_buffer->start_date); p_buffer->start_date = start_date; /* Actually run the resampler now. */ if ( p_input->i_nb_resamplers > 0 ) { aout_FiltersPlay( p_aout, p_input->pp_resamplers, p_input->i_nb_resamplers, &p_buffer ); } vlc_mutex_lock( &p_aout->input_fifos_lock ); aout_FifoPush( p_aout, &p_input->fifo, p_buffer ); vlc_mutex_unlock( &p_aout->input_fifos_lock ); return 0;}static int ChangeFiltersString( aout_instance_t * p_aout, char *psz_name, vlc_bool_t b_add ){ vlc_value_t val; char *psz_parser; var_Get( p_aout, "audio-filter", &val ); if( !val.psz_string ) val.psz_string = strdup(""); psz_parser = strstr( val.psz_string, psz_name ); if( b_add ) { if( !psz_parser ) { psz_parser = val.psz_string; asprintf( &val.psz_string, (*val.psz_string) ? "%s:%s" : "%s%s", val.psz_string, psz_name ); free( psz_parser ); } else { return 0; } } else { if( psz_parser ) { memmove( psz_parser, psz_parser + strlen(psz_name) + (*(psz_parser + strlen(psz_name)) == ':' ? 1 : 0 ), strlen(psz_parser + strlen(psz_name)) + 1 ); } else { free( val.psz_string ); return 0; } } var_Set( p_aout, "audio-filter", val ); free( val.psz_string ); return 1;}static int VisualizationCallback( vlc_object_t *p_this, char const *psz_cmd, vlc_value_t oldval, vlc_value_t newval, void *p_data ){ aout_instance_t *p_aout = (aout_instance_t *)p_this; char *psz_mode = newval.psz_string; vlc_value_t val; int i; if( !psz_mode || !*psz_mode ) { ChangeFiltersString( p_aout, "goom", VLC_FALSE ); ChangeFiltersString( p_aout, "visual", VLC_FALSE ); ChangeFiltersString( p_aout, "galaktos", VLC_FALSE ); } else { if( !strcmp( "goom", psz_mode ) ) { ChangeFiltersString( p_aout, "visual", VLC_FALSE ); ChangeFiltersString( p_aout, "goom", VLC_TRUE ); ChangeFiltersString( p_aout, "galaktos", VLC_FALSE ); } else if( !strcmp( "galaktos", psz_mode ) ) { ChangeFiltersString( p_aout, "visual", VLC_FALSE ); ChangeFiltersString( p_aout, "goom", VLC_FALSE ); ChangeFiltersString( p_aout, "galaktos", VLC_TRUE ); } else { val.psz_string = psz_mode; var_Create( p_aout, "effect-list", VLC_VAR_STRING ); var_Set( p_aout, "effect-list", val ); ChangeFiltersString( p_aout, "goom", VLC_FALSE ); ChangeFiltersString( p_aout, "visual", VLC_TRUE ); ChangeFiltersString( p_aout, "galaktos", VLC_FALSE ); } } /* That sucks */ for( i = 0; i < p_aout->i_nb_inputs; i++ ) { p_aout->pp_inputs[i]->b_restart = VLC_TRUE; } return VLC_SUCCESS;}static int EqualizerCallback( vlc_object_t *p_this, char const *psz_cmd, vlc_value_t oldval, vlc_value_t newval, void *p_data ){ aout_instance_t *p_aout = (aout_instance_t *)p_this; char *psz_mode = newval.psz_string; vlc_value_t val; int i; int i_ret; if( !psz_mode || !*psz_mode ) { i_ret = ChangeFiltersString( p_aout, "equalizer", VLC_FALSE ); } else { val.psz_string = psz_mode; var_Create( p_aout, "equalizer-preset", VLC_VAR_STRING ); var_Set( p_aout, "equalizer-preset", val ); i_ret = ChangeFiltersString( p_aout, "equalizer", VLC_TRUE ); } /* That sucks */ if( i_ret == 1 ) { for( i = 0; i < p_aout->i_nb_inputs; i++ ) { p_aout->pp_inputs[i]->b_restart = VLC_TRUE; } } return VLC_SUCCESS;}static aout_filter_t * allocateUserChannelMixer( aout_instance_t * p_aout, audio_sample_format_t * p_input_format, audio_sample_format_t * p_output_format ){ aout_filter_t * p_channel_mixer; /* Retreive user preferred channel mixer */ char * psz_name = config_GetPsz( p_aout, "audio-channel-mixer" ); /* Not specified => let the main pipeline do the mixing */ if ( ! psz_name ) return NULL; /* Debug information */ aout_FormatsPrint( p_aout, "channel mixer", p_input_format, p_output_format ); /* Create a VLC object */ p_channel_mixer = vlc_object_create( p_aout, sizeof(aout_filter_t) ); if( p_channel_mixer == NULL ) { msg_Err( p_aout, "cannot add user channel mixer %s", psz_name ); return NULL; } vlc_object_attach( p_channel_mixer , p_aout ); /* Attach the suitable module */ memcpy( &p_channel_mixer->input, p_input_format, sizeof(audio_sample_format_t) ); memcpy( &p_channel_mixer->output, p_output_format, sizeof(audio_sample_format_t) ); p_channel_mixer->p_module = module_Need( p_channel_mixer,"audio filter", psz_name, VLC_TRUE ); if( p_channel_mixer->p_module== NULL ) { msg_Err( p_aout, "cannot add user channel mixer %s", psz_name ); vlc_object_detach( p_channel_mixer ); vlc_object_destroy( p_channel_mixer ); return NULL; } p_channel_mixer->b_continuity = VLC_FALSE; /* Ok */ return p_channel_mixer;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -