2014-07-02 12:39:07 +03:00
/*
* Copyright ( c ) 2001 Heikki Leinonen
* Copyright ( c ) 2001 Chris Bagwell
* Copyright ( c ) 2003 Donnie Smith
* Copyright ( c ) 2014 Paul B Mahol
*
* This file is part of FFmpeg .
*
* FFmpeg is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* FFmpeg 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
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
*/
# include <float.h> /* DBL_MAX */
2021-09-08 09:42:27 +02:00
# include "libavutil/avassert.h"
2024-03-25 02:30:37 +02:00
# include "libavutil/mem.h"
2014-07-02 12:39:07 +03:00
# include "libavutil/opt.h"
# include "audio.h"
2023-05-23 00:30:22 +02:00
# include "filters.h"
2014-07-02 12:39:07 +03:00
# include "avfilter.h"
2018-10-15 17:44:56 +02:00
enum SilenceDetect {
2023-05-25 23:06:50 +02:00
D_AVG ,
2018-10-15 17:44:56 +02:00
D_RMS ,
2023-05-25 23:06:50 +02:00
D_PEAK ,
2023-05-26 14:10:38 +02:00
D_MEDIAN ,
2023-05-27 20:52:00 +02:00
D_PTP ,
2023-05-28 17:37:55 +02:00
D_DEV ,
2023-05-25 23:06:50 +02:00
D_NB
2018-10-15 17:44:56 +02:00
} ;
2023-05-28 12:01:27 +02:00
enum TimestampMode {
TS_WRITE ,
TS_COPY ,
TS_NB
} ;
2018-10-15 17:52:56 +02:00
enum ThresholdMode {
T_ANY ,
T_ALL ,
} ;
2014-07-02 12:39:07 +03:00
typedef struct SilenceRemoveContext {
const AVClass * class ;
2023-05-23 00:30:22 +02:00
int start_mode ;
2014-07-02 12:39:07 +03:00
int start_periods ;
int64_t start_duration ;
2018-10-08 20:43:14 +02:00
int64_t start_duration_opt ;
2014-07-02 12:39:07 +03:00
double start_threshold ;
2018-10-08 20:43:14 +02:00
int64_t start_silence ;
int64_t start_silence_opt ;
2014-07-02 12:39:07 +03:00
2023-05-23 00:30:22 +02:00
int stop_mode ;
2014-07-02 12:39:07 +03:00
int stop_periods ;
int64_t stop_duration ;
2018-10-08 20:43:14 +02:00
int64_t stop_duration_opt ;
2014-07-02 12:39:07 +03:00
double stop_threshold ;
2018-10-08 20:43:14 +02:00
int64_t stop_silence ;
int64_t stop_silence_opt ;
2014-07-02 12:39:07 +03:00
2021-09-07 19:20:38 +02:00
int64_t window_duration_opt ;
2023-05-28 12:01:27 +02:00
int timestamp_mode ;
2023-05-23 00:30:22 +02:00
int start_found_periods ;
int stop_found_periods ;
int start_sample_count ;
int start_silence_count ;
int stop_sample_count ;
int stop_silence_count ;
AVFrame * start_window ;
AVFrame * stop_window ;
2023-05-25 23:06:50 +02:00
int * start_front ;
int * start_back ;
int * stop_front ;
int * stop_back ;
2021-09-07 19:20:38 +02:00
int64_t window_duration ;
2023-05-28 14:35:46 +02:00
int cache_size ;
2014-07-02 12:39:07 +03:00
2023-05-23 00:30:22 +02:00
int start_window_pos ;
int start_window_size ;
int stop_window_pos ;
int stop_window_size ;
double * start_cache ;
double * stop_cache ;
AVFrame * start_queuef ;
int start_queue_pos ;
int start_queue_size ;
AVFrame * stop_queuef ;
int stop_queue_pos ;
int stop_queue_size ;
2014-07-02 12:39:07 +03:00
int restart ;
2023-05-23 00:30:22 +02:00
int found_nonsilence ;
2014-07-02 12:39:07 +03:00
int64_t next_pts ;
2015-12-27 21:45:46 +02:00
int detection ;
2021-09-08 15:15:19 +02:00
2023-05-25 23:06:50 +02:00
float ( * compute_flt ) ( float * c , float s , float ws , int size , int * front , int * back ) ;
double ( * compute_dbl ) ( double * c , double s , double ws , int size , int * front , int * back ) ;
2014-07-02 12:39:07 +03:00
} SilenceRemoveContext ;
# define OFFSET(x) offsetof(SilenceRemoveContext, x)
2018-10-08 20:43:14 +02:00
# define AF AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_AUDIO_PARAM
2023-05-27 10:12:37 +02:00
# define AFR AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
2018-10-08 20:43:14 +02:00
2014-07-02 12:39:07 +03:00
static const AVOption silenceremove_options [ ] = {
2021-09-08 13:06:43 +02:00
{ " start_periods " , " set periods of silence parts to skip from start " , OFFSET ( start_periods ) , AV_OPT_TYPE_INT , { . i64 = 0 } , 0 , 9000 , AF } ,
2018-10-15 16:26:16 +02:00
{ " start_duration " , " set start duration of non-silence part " , OFFSET ( start_duration_opt ) , AV_OPT_TYPE_DURATION , { . i64 = 0 } , 0 , INT32_MAX , AF } ,
2023-05-27 10:12:37 +02:00
{ " start_threshold " , " set threshold for start silence detection " , OFFSET ( start_threshold ) , AV_OPT_TYPE_DOUBLE , { . dbl = 0 } , 0 , DBL_MAX , AFR } ,
2018-10-15 16:26:16 +02:00
{ " start_silence " , " set start duration of silence part to keep " , OFFSET ( start_silence_opt ) , AV_OPT_TYPE_DURATION , { . i64 = 0 } , 0 , INT32_MAX , AF } ,
2024-02-11 16:41:05 +02:00
{ " start_mode " , " set which channel will trigger trimming from start " , OFFSET ( start_mode ) , AV_OPT_TYPE_INT , { . i64 = T_ANY } , T_ANY , T_ALL , AFR , . unit = " mode " } ,
{ " any " , 0 , 0 , AV_OPT_TYPE_CONST , { . i64 = T_ANY } , 0 , 0 , AFR , . unit = " mode " } ,
{ " all " , 0 , 0 , AV_OPT_TYPE_CONST , { . i64 = T_ALL } , 0 , 0 , AFR , . unit = " mode " } ,
2021-09-08 13:06:43 +02:00
{ " stop_periods " , " set periods of silence parts to skip from end " , OFFSET ( stop_periods ) , AV_OPT_TYPE_INT , { . i64 = 0 } , - 9000 , 9000 , AF } ,
2023-05-23 00:30:22 +02:00
{ " stop_duration " , " set stop duration of silence part " , OFFSET ( stop_duration_opt ) , AV_OPT_TYPE_DURATION , { . i64 = 0 } , 0 , INT32_MAX , AF } ,
2023-05-27 10:12:37 +02:00
{ " stop_threshold " , " set threshold for stop silence detection " , OFFSET ( stop_threshold ) , AV_OPT_TYPE_DOUBLE , { . dbl = 0 } , 0 , DBL_MAX , AFR } ,
2018-10-15 16:26:16 +02:00
{ " stop_silence " , " set stop duration of silence part to keep " , OFFSET ( stop_silence_opt ) , AV_OPT_TYPE_DURATION , { . i64 = 0 } , 0 , INT32_MAX , AF } ,
2024-02-11 16:41:05 +02:00
{ " stop_mode " , " set which channel will trigger trimming from end " , OFFSET ( stop_mode ) , AV_OPT_TYPE_INT , { . i64 = T_ALL } , T_ANY , T_ALL , AFR , . unit = " mode " } ,
{ " detection " , " set how silence is detected " , OFFSET ( detection ) , AV_OPT_TYPE_INT , { . i64 = D_RMS } , 0 , D_NB - 1 , AF , . unit = " detection " } ,
{ " avg " , " use mean absolute values of samples " , 0 , AV_OPT_TYPE_CONST , { . i64 = D_AVG } , 0 , 0 , AF , . unit = " detection " } ,
{ " rms " , " use root mean squared values of samples " , 0 , AV_OPT_TYPE_CONST , { . i64 = D_RMS } , 0 , 0 , AF , . unit = " detection " } ,
{ " peak " , " use max absolute values of samples " , 0 , AV_OPT_TYPE_CONST , { . i64 = D_PEAK } , 0 , 0 , AF , . unit = " detection " } ,
{ " median " , " use median of absolute values of samples " , 0 , AV_OPT_TYPE_CONST , { . i64 = D_MEDIAN } , 0 , 0 , AF , . unit = " detection " } ,
{ " ptp " , " use absolute of max peak to min peak difference " , 0 , AV_OPT_TYPE_CONST , { . i64 = D_PTP } , 0 , 0 , AF , . unit = " detection " } ,
{ " dev " , " use standard deviation from values of samples " , 0 , AV_OPT_TYPE_CONST , { . i64 = D_DEV } , 0 , 0 , AF , . unit = " detection " } ,
2021-09-07 19:20:38 +02:00
{ " window " , " set duration of window for silence detection " , OFFSET ( window_duration_opt ) , AV_OPT_TYPE_DURATION , { . i64 = 20000 } , 0 , 100000000 , AF } ,
2024-02-11 16:41:05 +02:00
{ " timestamp " , " set how every output frame timestamp is processed " , OFFSET ( timestamp_mode ) , AV_OPT_TYPE_INT , { . i64 = TS_WRITE } , 0 , TS_NB - 1 , AF , . unit = " timestamp " } ,
{ " write " , " full timestamps rewrite, keep only the start time " , 0 , AV_OPT_TYPE_CONST , { . i64 = TS_WRITE } , 0 , 0 , AF , . unit = " timestamp " } ,
{ " copy " , " non-dropped frames are left with same timestamp " , 0 , AV_OPT_TYPE_CONST , { . i64 = TS_COPY } , 0 , 0 , AF , . unit = " timestamp " } ,
2014-07-02 12:39:07 +03:00
{ NULL }
} ;
AVFILTER_DEFINE_CLASS ( silenceremove ) ;
2023-05-23 00:30:22 +02:00
# define DEPTH 32
# include "silenceremove_template.c"
2021-07-25 15:38:33 +02:00
2023-05-23 00:30:22 +02:00
# undef DEPTH
# define DEPTH 64
# include "silenceremove_template.c"
2015-12-27 21:45:46 +02:00
2014-07-02 12:39:07 +03:00
static av_cold int init ( AVFilterContext * ctx )
{
SilenceRemoveContext * s = ctx - > priv ;
if ( s - > stop_periods < 0 ) {
s - > stop_periods = - s - > stop_periods ;
s - > restart = 1 ;
}
return 0 ;
}
2023-05-23 00:30:22 +02:00
static void clear_windows ( SilenceRemoveContext * s )
2014-07-02 12:39:07 +03:00
{
2023-05-23 00:30:22 +02:00
av_samples_set_silence ( s - > start_window - > extended_data , 0 ,
s - > start_window - > nb_samples ,
s - > start_window - > ch_layout . nb_channels ,
s - > start_window - > format ) ;
av_samples_set_silence ( s - > stop_window - > extended_data , 0 ,
s - > stop_window - > nb_samples ,
s - > stop_window - > ch_layout . nb_channels ,
s - > stop_window - > format ) ;
s - > start_window_pos = 0 ;
s - > start_window_size = 0 ;
s - > stop_window_pos = 0 ;
s - > stop_window_size = 0 ;
s - > start_queue_pos = 0 ;
s - > start_queue_size = 0 ;
s - > stop_queue_pos = 0 ;
s - > stop_queue_size = 0 ;
2014-07-02 12:39:07 +03:00
}
static int config_input ( AVFilterLink * inlink )
{
AVFilterContext * ctx = inlink - > dst ;
SilenceRemoveContext * s = ctx - > priv ;
2019-07-02 18:06:28 +02:00
s - > next_pts = AV_NOPTS_VALUE ;
2021-09-07 19:20:38 +02:00
s - > window_duration = av_rescale ( s - > window_duration_opt , inlink - > sample_rate ,
AV_TIME_BASE ) ;
s - > window_duration = FFMAX ( 1 , s - > window_duration ) ;
2014-07-02 12:39:07 +03:00
2018-10-08 20:43:14 +02:00
s - > start_duration = av_rescale ( s - > start_duration_opt , inlink - > sample_rate ,
2014-07-02 12:39:07 +03:00
AV_TIME_BASE ) ;
2018-10-08 20:43:14 +02:00
s - > start_silence = av_rescale ( s - > start_silence_opt , inlink - > sample_rate ,
AV_TIME_BASE ) ;
2023-05-23 00:30:22 +02:00
s - > stop_duration = av_rescale ( s - > stop_duration_opt , inlink - > sample_rate ,
2018-10-08 20:43:14 +02:00
AV_TIME_BASE ) ;
2023-05-23 00:30:22 +02:00
s - > stop_silence = av_rescale ( s - > stop_silence_opt , inlink - > sample_rate ,
2014-07-02 12:39:07 +03:00
AV_TIME_BASE ) ;
2023-05-23 00:30:22 +02:00
s - > start_found_periods = 0 ;
s - > stop_found_periods = 0 ;
2014-07-02 12:39:07 +03:00
2023-05-23 00:30:22 +02:00
return 0 ;
}
2018-10-08 20:43:14 +02:00
2023-05-23 00:30:22 +02:00
static int config_output ( AVFilterLink * outlink )
{
AVFilterContext * ctx = outlink - > src ;
SilenceRemoveContext * s = ctx - > priv ;
2014-07-02 12:39:07 +03:00
2023-05-28 14:35:46 +02:00
switch ( s - > detection ) {
case D_AVG :
case D_RMS :
s - > cache_size = 1 ;
break ;
2023-05-28 17:37:55 +02:00
case D_DEV :
s - > cache_size = 2 ;
break ;
2023-05-28 14:35:46 +02:00
case D_MEDIAN :
case D_PEAK :
case D_PTP :
s - > cache_size = s - > window_duration ;
break ;
}
2023-05-23 00:30:22 +02:00
s - > start_window = ff_get_audio_buffer ( outlink , s - > window_duration ) ;
s - > stop_window = ff_get_audio_buffer ( outlink , s - > window_duration ) ;
2023-05-28 14:35:46 +02:00
s - > start_cache = av_calloc ( outlink - > ch_layout . nb_channels , s - > cache_size * sizeof ( * s - > start_cache ) ) ;
s - > stop_cache = av_calloc ( outlink - > ch_layout . nb_channels , s - > cache_size * sizeof ( * s - > stop_cache ) ) ;
2023-05-25 23:06:50 +02:00
if ( ! s - > start_window | | ! s - > stop_window | | ! s - > start_cache | | ! s - > stop_cache )
2014-07-02 12:39:07 +03:00
return AVERROR ( ENOMEM ) ;
2023-05-23 00:30:22 +02:00
s - > start_queuef = ff_get_audio_buffer ( outlink , s - > start_silence + 1 ) ;
s - > stop_queuef = ff_get_audio_buffer ( outlink , s - > stop_silence + 1 ) ;
if ( ! s - > start_queuef | | ! s - > stop_queuef )
2018-10-08 20:43:14 +02:00
return AVERROR ( ENOMEM ) ;
2023-05-25 23:06:50 +02:00
s - > start_front = av_calloc ( outlink - > ch_layout . nb_channels , sizeof ( * s - > start_front ) ) ;
s - > start_back = av_calloc ( outlink - > ch_layout . nb_channels , sizeof ( * s - > start_back ) ) ;
s - > stop_front = av_calloc ( outlink - > ch_layout . nb_channels , sizeof ( * s - > stop_front ) ) ;
s - > stop_back = av_calloc ( outlink - > ch_layout . nb_channels , sizeof ( * s - > stop_back ) ) ;
if ( ! s - > start_front | | ! s - > start_back | | ! s - > stop_front | | ! s - > stop_back )
2023-05-23 00:30:22 +02:00
return AVERROR ( ENOMEM ) ;
2014-07-02 12:39:07 +03:00
2023-05-23 00:30:22 +02:00
clear_windows ( s ) ;
2014-07-02 12:39:07 +03:00
2023-05-23 00:30:22 +02:00
switch ( s - > detection ) {
2023-05-25 23:06:50 +02:00
case D_AVG :
s - > compute_flt = compute_avg_flt ;
s - > compute_dbl = compute_avg_dbl ;
break ;
2023-05-28 17:37:55 +02:00
case D_DEV :
s - > compute_flt = compute_dev_flt ;
s - > compute_dbl = compute_dev_dbl ;
break ;
2023-05-27 20:52:00 +02:00
case D_PTP :
s - > compute_flt = compute_ptp_flt ;
s - > compute_dbl = compute_ptp_dbl ;
break ;
2023-05-26 14:10:38 +02:00
case D_MEDIAN :
s - > compute_flt = compute_median_flt ;
s - > compute_dbl = compute_median_dbl ;
break ;
2023-05-23 00:30:22 +02:00
case D_PEAK :
s - > compute_flt = compute_peak_flt ;
s - > compute_dbl = compute_peak_dbl ;
2021-07-25 15:38:33 +02:00
break ;
2023-05-23 00:30:22 +02:00
case D_RMS :
s - > compute_flt = compute_rms_flt ;
s - > compute_dbl = compute_rms_dbl ;
2021-07-25 15:38:33 +02:00
break ;
}
2014-07-02 12:39:07 +03:00
return 0 ;
}
2023-05-23 00:30:22 +02:00
static int filter_frame ( AVFilterLink * outlink , AVFrame * in )
2014-07-02 12:39:07 +03:00
{
2023-05-23 00:30:22 +02:00
const int nb_channels = outlink - > ch_layout . nb_channels ;
AVFilterContext * ctx = outlink - > src ;
2014-07-02 12:39:07 +03:00
SilenceRemoveContext * s = ctx - > priv ;
2023-05-23 00:30:22 +02:00
int max_out_nb_samples ;
int out_nb_samples = 0 ;
int in_nb_samples ;
const double * srcd ;
const float * srcf ;
2014-07-02 12:39:07 +03:00
AVFrame * out ;
2023-05-23 00:30:22 +02:00
double * dstd ;
float * dstf ;
2014-07-02 12:39:07 +03:00
2019-07-02 18:06:28 +02:00
if ( s - > next_pts = = AV_NOPTS_VALUE )
s - > next_pts = in - > pts ;
2023-05-23 00:30:22 +02:00
in_nb_samples = in - > nb_samples ;
max_out_nb_samples = in - > nb_samples +
s - > start_silence +
s - > stop_silence ;
if ( max_out_nb_samples < = 0 ) {
av_frame_free ( & in ) ;
ff_filter_set_ready ( ctx , 100 ) ;
return 0 ;
}
2014-07-02 12:39:07 +03:00
2023-05-23 00:30:22 +02:00
out = ff_get_audio_buffer ( outlink , max_out_nb_samples ) ;
if ( ! out ) {
av_frame_free ( & in ) ;
return AVERROR ( ENOMEM ) ;
}
2014-07-02 12:39:07 +03:00
2023-05-28 12:01:27 +02:00
if ( s - > timestamp_mode = = TS_WRITE )
out - > pts = s - > next_pts ;
else
out - > pts = in - > pts ;
2014-07-02 12:39:07 +03:00
2023-05-23 00:30:22 +02:00
switch ( outlink - > format ) {
case AV_SAMPLE_FMT_FLT :
srcf = ( const float * ) in - > data [ 0 ] ;
dstf = ( float * ) out - > data [ 0 ] ;
if ( s - > start_periods > 0 & & s - > stop_periods > 0 ) {
2023-05-27 11:13:48 +02:00
const float * src = srcf ;
if ( s - > start_found_periods > = 0 ) {
for ( int n = 0 ; n < in_nb_samples ; n + + ) {
filter_start_flt ( ctx , src + n * nb_channels ,
dstf , & out_nb_samples ,
nb_channels ) ;
}
in_nb_samples = out_nb_samples ;
out_nb_samples = 0 ;
src = dstf ;
2018-10-08 20:43:14 +02:00
}
2023-05-23 00:30:22 +02:00
for ( int n = 0 ; n < in_nb_samples ; n + + ) {
2023-05-27 11:13:48 +02:00
filter_stop_flt ( ctx , src + n * nb_channels ,
2023-05-23 00:30:22 +02:00
dstf , & out_nb_samples ,
nb_channels ) ;
2018-10-08 20:43:14 +02:00
}
2023-05-23 00:30:22 +02:00
} else if ( s - > start_periods > 0 ) {
for ( int n = 0 ; n < in_nb_samples ; n + + ) {
filter_start_flt ( ctx , srcf + n * nb_channels ,
dstf , & out_nb_samples ,
nb_channels ) ;
}
} else if ( s - > stop_periods > 0 ) {
for ( int n = 0 ; n < in_nb_samples ; n + + ) {
filter_stop_flt ( ctx , srcf + n * nb_channels ,
dstf , & out_nb_samples ,
nb_channels ) ;
2014-07-02 12:39:07 +03:00
}
}
break ;
2023-05-23 00:30:22 +02:00
case AV_SAMPLE_FMT_DBL :
srcd = ( const double * ) in - > data [ 0 ] ;
dstd = ( double * ) out - > data [ 0 ] ;
if ( s - > start_periods > 0 & & s - > stop_periods > 0 ) {
2023-05-27 11:13:48 +02:00
const double * src = srcd ;
if ( s - > start_found_periods > = 0 ) {
for ( int n = 0 ; n < in_nb_samples ; n + + ) {
filter_start_dbl ( ctx , src + n * nb_channels ,
dstd , & out_nb_samples ,
nb_channels ) ;
}
in_nb_samples = out_nb_samples ;
out_nb_samples = 0 ;
src = dstd ;
2023-05-23 00:30:22 +02:00
}
for ( int n = 0 ; n < in_nb_samples ; n + + ) {
2023-05-27 11:13:48 +02:00
filter_stop_dbl ( ctx , src + n * nb_channels ,
2023-05-23 00:30:22 +02:00
dstd , & out_nb_samples ,
nb_channels ) ;
}
} else if ( s - > start_periods > 0 ) {
for ( int n = 0 ; n < in_nb_samples ; n + + ) {
filter_start_dbl ( ctx , srcd + n * nb_channels ,
dstd , & out_nb_samples ,
nb_channels ) ;
}
} else if ( s - > stop_periods > 0 ) {
for ( int n = 0 ; n < in_nb_samples ; n + + ) {
filter_stop_dbl ( ctx , srcd + n * nb_channels ,
dstd , & out_nb_samples ,
nb_channels ) ;
}
2014-07-02 12:39:07 +03:00
}
break ;
}
av_frame_free ( & in ) ;
2023-05-23 00:30:22 +02:00
if ( out_nb_samples > 0 ) {
s - > next_pts + = out_nb_samples ;
out - > nb_samples = out_nb_samples ;
return ff_filter_frame ( outlink , out ) ;
2021-09-08 15:15:19 +02:00
}
2023-05-23 00:30:22 +02:00
av_frame_free ( & out ) ;
ff_filter_set_ready ( ctx , 100 ) ;
return 0 ;
2014-07-02 12:39:07 +03:00
}
2023-05-23 00:30:22 +02:00
static int activate ( AVFilterContext * ctx )
2014-07-02 12:39:07 +03:00
{
2023-05-23 00:30:22 +02:00
AVFilterLink * outlink = ctx - > outputs [ 0 ] ;
AVFilterLink * inlink = ctx - > inputs [ 0 ] ;
2014-07-02 12:39:07 +03:00
SilenceRemoveContext * s = ctx - > priv ;
2023-05-23 00:30:22 +02:00
AVFrame * in ;
2014-07-02 12:39:07 +03:00
int ret ;
2023-05-23 00:30:22 +02:00
FF_FILTER_FORWARD_STATUS_BACK ( outlink , inlink ) ;
2014-07-02 12:39:07 +03:00
2023-05-23 00:30:22 +02:00
ret = ff_inlink_consume_frame ( inlink , & in ) ;
if ( ret < 0 )
return ret ;
if ( ret > 0 ) {
2023-05-26 09:54:40 +02:00
if ( s - > start_periods = = 1 & & s - > stop_periods = = 0 & &
s - > start_found_periods < 0 ) {
2023-05-28 12:01:27 +02:00
if ( s - > timestamp_mode = = TS_WRITE )
in - > pts = s - > next_pts ;
2023-05-26 09:54:40 +02:00
s - > next_pts + = in - > nb_samples ;
return ff_filter_frame ( outlink , in ) ;
}
2023-05-23 00:30:22 +02:00
if ( s - > start_periods = = 0 & & s - > stop_periods = = 0 )
return ff_filter_frame ( outlink , in ) ;
return filter_frame ( outlink , in ) ;
}
2017-05-15 14:05:17 +02:00
2023-05-23 00:30:22 +02:00
FF_FILTER_FORWARD_STATUS ( inlink , outlink ) ;
FF_FILTER_FORWARD_WANTED ( outlink , inlink ) ;
2017-05-15 14:05:17 +02:00
2023-05-23 00:30:22 +02:00
return FFERROR_NOT_READY ;
2014-07-02 12:39:07 +03:00
}
static av_cold void uninit ( AVFilterContext * ctx )
{
SilenceRemoveContext * s = ctx - > priv ;
2023-05-23 00:30:22 +02:00
av_frame_free ( & s - > start_window ) ;
av_frame_free ( & s - > stop_window ) ;
av_frame_free ( & s - > start_queuef ) ;
av_frame_free ( & s - > stop_queuef ) ;
2023-05-25 23:06:50 +02:00
2023-05-23 00:30:22 +02:00
av_freep ( & s - > start_cache ) ;
av_freep ( & s - > stop_cache ) ;
2023-05-25 23:06:50 +02:00
av_freep ( & s - > start_front ) ;
av_freep ( & s - > start_back ) ;
av_freep ( & s - > stop_front ) ;
av_freep ( & s - > stop_back ) ;
2014-07-02 12:39:07 +03:00
}
static const AVFilterPad silenceremove_inputs [ ] = {
{
. name = " default " ,
. type = AVMEDIA_TYPE_AUDIO ,
. config_props = config_input ,
} ,
} ;
static const AVFilterPad silenceremove_outputs [ ] = {
{
2023-05-23 00:30:22 +02:00
. name = " default " ,
. type = AVMEDIA_TYPE_AUDIO ,
. config_props = config_output ,
2014-07-02 12:39:07 +03:00
} ,
} ;
2021-04-19 18:33:56 +02:00
const AVFilter ff_af_silenceremove = {
2014-07-02 12:39:07 +03:00
. name = " silenceremove " ,
. description = NULL_IF_CONFIG_SMALL ( " Remove silence. " ) ,
. priv_size = sizeof ( SilenceRemoveContext ) ,
. priv_class = & silenceremove_class ,
. init = init ,
2023-05-23 00:30:22 +02:00
. activate = activate ,
2014-07-02 12:39:07 +03:00
. uninit = uninit ,
2021-08-12 13:05:31 +02:00
FILTER_INPUTS ( silenceremove_inputs ) ,
FILTER_OUTPUTS ( silenceremove_outputs ) ,
2023-05-23 00:30:22 +02:00
FILTER_SAMPLEFMTS ( AV_SAMPLE_FMT_FLT ,
AV_SAMPLE_FMT_DBL ) ,
2023-05-27 10:12:37 +02:00
. process_command = ff_filter_process_command ,
2023-05-27 11:03:18 +02:00
. flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL ,
2014-07-02 12:39:07 +03:00
} ;