2 * Copyright (c) 2012 Michael Niedermayer
4 * This file is part of FFmpeg.
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 * Based on af_aresample.c
28 #include "libavutil/avstring.h"
29 #include "libavutil/channel_layout.h"
30 #include "libavutil/opt.h"
31 #include "libavutil/samplefmt.h"
32 #include "libavutil/avassert.h"
42 int64_t pad_len
, pad_len_left
;
43 int64_t whole_len
, whole_len_left
;
46 #define OFFSET(x) offsetof(APadContext, x)
47 #define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
49 static const AVOption apad_options
[] = {
50 { "packet_size", "set silence packet size", OFFSET(packet_size
), AV_OPT_TYPE_INT
, { .i64
= 4096 }, 0, INT_MAX
, A
},
51 { "pad_len", "set number of samples of silence to add", OFFSET(pad_len
), AV_OPT_TYPE_INT64
, { .i64
= -1 }, -1, INT64_MAX
, A
},
52 { "whole_len", "set minimum target number of samples in the audio stream", OFFSET(whole_len
), AV_OPT_TYPE_INT64
, { .i64
= -1 }, -1, INT64_MAX
, A
},
56 AVFILTER_DEFINE_CLASS(apad
);
58 static av_cold
int init(AVFilterContext
*ctx
)
60 APadContext
*apad
= ctx
->priv
;
62 apad
->next_pts
= AV_NOPTS_VALUE
;
63 if (apad
->whole_len
>= 0 && apad
->pad_len
>= 0) {
64 av_log(ctx
, AV_LOG_ERROR
, "Both whole and pad length are set, this is not possible\n");
65 return AVERROR(EINVAL
);
67 apad
->pad_len_left
= apad
->pad_len
;
68 apad
->whole_len_left
= apad
->whole_len
;
73 static int filter_frame(AVFilterLink
*inlink
, AVFrame
*frame
)
75 AVFilterContext
*ctx
= inlink
->dst
;
76 APadContext
*apad
= ctx
->priv
;
78 if (apad
->whole_len
>= 0) {
79 apad
->whole_len_left
= FFMAX(apad
->whole_len_left
- frame
->nb_samples
, 0);
80 av_log(ctx
, AV_LOG_DEBUG
,
81 "n_out:%d whole_len_left:%"PRId64
"\n", frame
->nb_samples
, apad
->whole_len_left
);
84 apad
->next_pts
= frame
->pts
+ av_rescale_q(frame
->nb_samples
, (AVRational
){1, inlink
->sample_rate
}, inlink
->time_base
);
85 return ff_filter_frame(ctx
->outputs
[0], frame
);
88 static int request_frame(AVFilterLink
*outlink
)
90 AVFilterContext
*ctx
= outlink
->src
;
91 APadContext
*apad
= ctx
->priv
;
94 ret
= ff_request_frame(ctx
->inputs
[0]);
96 if (ret
== AVERROR_EOF
&& !ctx
->is_disabled
) {
97 int n_out
= apad
->packet_size
;
98 AVFrame
*outsamplesref
;
100 if (apad
->whole_len
>= 0 && apad
->pad_len
< 0) {
101 apad
->pad_len
= apad
->pad_len_left
= apad
->whole_len_left
;
103 if (apad
->pad_len
>=0 || apad
->whole_len
>= 0) {
104 n_out
= FFMIN(n_out
, apad
->pad_len_left
);
105 apad
->pad_len_left
-= n_out
;
106 av_log(ctx
, AV_LOG_DEBUG
,
107 "padding n_out:%d pad_len_left:%"PRId64
"\n", n_out
, apad
->pad_len_left
);
113 outsamplesref
= ff_get_audio_buffer(outlink
, n_out
);
115 return AVERROR(ENOMEM
);
117 av_assert0(outsamplesref
->sample_rate
== outlink
->sample_rate
);
118 av_assert0(outsamplesref
->nb_samples
== n_out
);
120 av_samples_set_silence(outsamplesref
->extended_data
, 0,
122 av_frame_get_channels(outsamplesref
),
123 outsamplesref
->format
);
125 outsamplesref
->pts
= apad
->next_pts
;
126 if (apad
->next_pts
!= AV_NOPTS_VALUE
)
127 apad
->next_pts
+= av_rescale_q(n_out
, (AVRational
){1, outlink
->sample_rate
}, outlink
->time_base
);
129 return ff_filter_frame(outlink
, outsamplesref
);
134 static const AVFilterPad apad_inputs
[] = {
137 .type
= AVMEDIA_TYPE_AUDIO
,
138 .filter_frame
= filter_frame
,
143 static const AVFilterPad apad_outputs
[] = {
146 .request_frame
= request_frame
,
147 .type
= AVMEDIA_TYPE_AUDIO
,
152 AVFilter ff_af_apad
= {
154 .description
= NULL_IF_CONFIG_SMALL("Pad audio with silence."),
156 .priv_size
= sizeof(APadContext
),
157 .inputs
= apad_inputs
,
158 .outputs
= apad_outputs
,
159 .priv_class
= &apad_class
,
160 .flags
= AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL
,