#include "libavutil/audio_fifo.h"
#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
+#include "libavutil/common.h"
#include "libavutil/float_dsp.h"
#include "libavutil/mathematics.h"
#include "libavutil/opt.h"
#define OFFSET(x) offsetof(MixContext, x)
#define A AV_OPT_FLAG_AUDIO_PARAM
+#define F AV_OPT_FLAG_FILTERING_PARAM
static const AVOption amix_options[] = {
{ "inputs", "Number of inputs.",
- OFFSET(nb_inputs), AV_OPT_TYPE_INT, { 2 }, 1, 32, A },
+ OFFSET(nb_inputs), AV_OPT_TYPE_INT, { 2 }, 1, 32, A|F },
{ "duration", "How to determine the end-of-stream.",
- OFFSET(duration_mode), AV_OPT_TYPE_INT, { DURATION_LONGEST }, 0, 2, A, "duration" },
- { "longest", "Duration of longest input.", 0, AV_OPT_TYPE_CONST, { DURATION_LONGEST }, INT_MIN, INT_MAX, A, "duration" },
- { "shortest", "Duration of shortest input.", 0, AV_OPT_TYPE_CONST, { DURATION_SHORTEST }, INT_MIN, INT_MAX, A, "duration" },
- { "first", "Duration of first input.", 0, AV_OPT_TYPE_CONST, { DURATION_FIRST }, INT_MIN, INT_MAX, A, "duration" },
+ OFFSET(duration_mode), AV_OPT_TYPE_INT, { DURATION_LONGEST }, 0, 2, A|F, "duration" },
+ { "longest", "Duration of longest input.", 0, AV_OPT_TYPE_CONST, { DURATION_LONGEST }, INT_MIN, INT_MAX, A|F, "duration" },
+ { "shortest", "Duration of shortest input.", 0, AV_OPT_TYPE_CONST, { DURATION_SHORTEST }, INT_MIN, INT_MAX, A|F, "duration" },
+ { "first", "Duration of first input.", 0, AV_OPT_TYPE_CONST, { DURATION_FIRST }, INT_MIN, INT_MAX, A|F, "duration" },
{ "dropout_transition", "Transition time, in seconds, for volume "
"renormalization when an input stream ends.",
- OFFSET(dropout_transition), AV_OPT_TYPE_FLOAT, { 2.0 }, 0, INT_MAX, A },
+ OFFSET(dropout_transition), AV_OPT_TYPE_FLOAT, { 2.0 }, 0, INT_MAX, A|F },
{ NULL },
};
av_get_channel_layout_string(buf, sizeof(buf), -1, outlink->channel_layout);
av_log(ctx, AV_LOG_VERBOSE,
- "inputs:%d fmt:%s srate:%"PRId64" cl:%s\n", s->nb_inputs,
+ "inputs:%d fmt:%s srate:%d cl:%s\n", s->nb_inputs,
av_get_sample_fmt_name(outlink->format), outlink->sample_rate, buf);
return 0;
if (s->next_pts != AV_NOPTS_VALUE)
s->next_pts += nb_samples;
- ff_filter_samples(outlink, out_buf);
-
- return 0;
+ return ff_filter_samples(outlink, out_buf);
}
/**
s->input_state[i] = INPUT_OFF;
continue;
}
- } else if (ret)
+ } else if (ret < 0)
return ret;
}
return 0;
available_samples = get_available_samples(s);
if (!available_samples)
- return 0;
+ return AVERROR(EAGAIN);
return output_frame(outlink, available_samples);
}
return AVERROR_EOF;
else
return AVERROR(EAGAIN);
- } else if (ret)
+ } else if (ret < 0)
return ret;
}
av_assert0(s->frame_list->nb_frames > 0);
ret = calc_active_inputs(s);
if (ret < 0)
return ret;
+ }
+ if (s->active_inputs > 1) {
available_samples = get_available_samples(s);
if (!available_samples)
- return 0;
+ return AVERROR(EAGAIN);
available_samples = FFMIN(available_samples, wanted_samples);
} else {
available_samples = wanted_samples;
return output_frame(outlink, available_samples);
}
-static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
+static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
{
AVFilterContext *ctx = inlink->dst;
MixContext *s = ctx->priv;
AVFilterLink *outlink = ctx->outputs[0];
- int i;
+ int i, ret = 0;
for (i = 0; i < ctx->nb_inputs; i++)
if (ctx->inputs[i] == inlink)
break;
if (i >= ctx->nb_inputs) {
av_log(ctx, AV_LOG_ERROR, "unknown input link\n");
- return;
+ ret = AVERROR(EINVAL);
+ goto fail;
}
if (i == 0) {
int64_t pts = av_rescale_q(buf->pts, inlink->time_base,
outlink->time_base);
- frame_list_add_frame(s->frame_list, buf->audio->nb_samples, pts);
+ ret = frame_list_add_frame(s->frame_list, buf->audio->nb_samples, pts);
+ if (ret < 0)
+ goto fail;
}
- av_audio_fifo_write(s->fifos[i], (void **)buf->extended_data,
- buf->audio->nb_samples);
+ ret = av_audio_fifo_write(s->fifos[i], (void **)buf->extended_data,
+ buf->audio->nb_samples);
+fail:
avfilter_unref_buffer(buf);
+
+ return ret;
}
-static int init(AVFilterContext *ctx, const char *args, void *opaque)
+static int init(AVFilterContext *ctx, const char *args)
{
MixContext *s = ctx->priv;
int i, ret;
s->class = &amix_class;
av_opt_set_defaults(s);
- if ((ret = av_set_options_string(s, args, "=", ":")) < 0) {
- av_log(ctx, AV_LOG_ERROR, "Error parsing options string '%s'.\n", args);
+ if ((ret = av_set_options_string(s, args, "=", ":")) < 0)
return ret;
- }
av_opt_free(s);
for (i = 0; i < s->nb_inputs; i++) {
.config_props = config_output,
.request_frame = request_frame },
{ .name = NULL}},
+ .priv_class = &amix_class,
};