lavfi/apad: fix logic when whole_len or pad_len options are specified

In particular, allow pad_len and whole_len to have value set to 0, which
means that no padding will be added. Previously a value set to 0 meant
that that the filter had to pad forever.

The new semantics is clearer, also simplifies scripting since the option
value might be automatically computed, so that no checks need to be done
in case it is 0.

The old semantics was never documented and the logic was broken (the
filter was always adding samples indefinitely), so this should not break
backward compatibility.
This commit is contained in:
Stefano Sabatini 2014-08-18 14:51:25 +02:00
parent 4728cdd880
commit aade9884e9
2 changed files with 21 additions and 15 deletions

View File

@ -39,17 +39,17 @@ typedef struct {
int64_t next_pts;
int packet_size;
int64_t pad_len;
int64_t whole_len;
int64_t pad_len, pad_len_left;
int64_t whole_len, whole_len_left;
} APadContext;
#define OFFSET(x) offsetof(APadContext, x)
#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
static const AVOption apad_options[] = {
{ "packet_size", "set silence packet size", OFFSET(packet_size), AV_OPT_TYPE_INT, { .i64 = 4096 }, 0, INT_MAX, A },
{ "pad_len", "number of samples of silence to add", OFFSET(pad_len), AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, INT64_MAX, A },
{ "whole_len", "target number of samples in the audio stream", OFFSET(whole_len), AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, INT64_MAX, A },
{ "packet_size", "set silence packet size", OFFSET(packet_size), AV_OPT_TYPE_INT, { .i64 = 4096 }, 0, INT_MAX, A },
{ "pad_len", "set number of samples of silence to add", OFFSET(pad_len), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, A },
{ "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 },
{ NULL }
};
@ -60,10 +60,12 @@ static av_cold int init(AVFilterContext *ctx)
APadContext *apad = ctx->priv;
apad->next_pts = AV_NOPTS_VALUE;
if (apad->whole_len && apad->pad_len) {
if (apad->whole_len >= 0 && apad->pad_len >= 0) {
av_log(ctx, AV_LOG_ERROR, "Both whole and pad length are set, this is not possible\n");
return AVERROR(EINVAL);
}
apad->pad_len_left = apad->pad_len;
apad->whole_len_left = apad->whole_len;
return 0;
}
@ -73,8 +75,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
AVFilterContext *ctx = inlink->dst;
APadContext *apad = ctx->priv;
if (apad->whole_len)
apad->whole_len -= frame->nb_samples;
if (apad->whole_len >= 0) {
apad->whole_len_left = FFMAX(apad->whole_len_left - frame->nb_samples, 0);
av_log(ctx, AV_LOG_DEBUG,
"n_out:%d whole_len_left:%"PRId64"\n", frame->nb_samples, apad->whole_len_left);
}
apad->next_pts = frame->pts + av_rescale_q(frame->nb_samples, (AVRational){1, inlink->sample_rate}, inlink->time_base);
return ff_filter_frame(ctx->outputs[0], frame);
@ -92,13 +97,14 @@ static int request_frame(AVFilterLink *outlink)
int n_out = apad->packet_size;
AVFrame *outsamplesref;
if (apad->whole_len > 0) {
apad->pad_len = apad->whole_len;
apad->whole_len = 0;
if (apad->whole_len >= 0 && apad->pad_len < 0) {
apad->pad_len = apad->pad_len_left = apad->whole_len_left;
}
if (apad->pad_len > 0) {
n_out = FFMIN(n_out, apad->pad_len);
apad->pad_len -= n_out;
if (apad->pad_len >=0 || apad->whole_len >= 0) {
n_out = FFMIN(n_out, apad->pad_len_left);
apad->pad_len_left -= n_out;
av_log(ctx, AV_LOG_DEBUG,
"padding n_out:%d pad_len_left:%"PRId64"\n", n_out, apad->pad_len_left);
}
if (!n_out)

View File

@ -31,7 +31,7 @@
#define LIBAVFILTER_VERSION_MAJOR 5
#define LIBAVFILTER_VERSION_MINOR 0
#define LIBAVFILTER_VERSION_MICRO 101
#define LIBAVFILTER_VERSION_MICRO 102
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
LIBAVFILTER_VERSION_MINOR, \