static int config_output(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; MixContext *s = ctx->priv; int i; char buf[64]; s->planar = av_sample_fmt_is_planar(outlink->format); s->sample_rate = outlink->sample_rate; #ifdef IDE_COMPILE outlink->time_base.num = 1; outlink->time_base.den = outlink->sample_rate; #else outlink->time_base = (AVRational){ 1, outlink->sample_rate }; #endif s->next_pts = AV_NOPTS_VALUE; s->frame_list = av_mallocz(sizeof(*s->frame_list)); if (!s->frame_list) return AVERROR(ENOMEM); s->fifos = av_mallocz(s->nb_inputs * sizeof(*s->fifos)); if (!s->fifos) return AVERROR(ENOMEM); s->nb_channels = av_get_channel_layout_nb_channels(outlink->channel_layout); for (i = 0; i < s->nb_inputs; i++) { s->fifos[i] = av_audio_fifo_alloc(outlink->format, s->nb_channels, 1024); if (!s->fifos[i]) return AVERROR(ENOMEM); } s->input_state = av_malloc(s->nb_inputs); if (!s->input_state) return AVERROR(ENOMEM); memset(s->input_state, INPUT_ON, s->nb_inputs); s->active_inputs = s->nb_inputs; s->input_scale = av_mallocz_array(s->nb_inputs, sizeof(*s->input_scale)); if (!s->input_scale) return AVERROR(ENOMEM); s->scale_norm = s->active_inputs; calculate_scales(s, 0); av_get_channel_layout_string(buf, sizeof(buf), -1, outlink->channel_layout); av_log(ctx, AV_LOG_VERBOSE, "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; }
/** * Read samples from the input FIFOs, mix, and write to the output link. */ static int output_frame(AVFilterLink *outlink, int nb_samples) { AVFilterContext *ctx = outlink->src; MixContext *s = ctx->priv; AVFrame *out_buf, *in_buf; int i; calculate_scales(s, nb_samples); out_buf = ff_get_audio_buffer(outlink, nb_samples); if (!out_buf) return AVERROR(ENOMEM); in_buf = ff_get_audio_buffer(outlink, nb_samples); if (!in_buf) { av_frame_free(&out_buf); return AVERROR(ENOMEM); } for (i = 0; i < s->nb_inputs; i++) { if (s->input_state[i] == INPUT_ON) { int planes, plane_size, p; av_audio_fifo_read(s->fifos[i], (void **)in_buf->extended_data, nb_samples); planes = s->planar ? s->nb_channels : 1; plane_size = nb_samples * (s->planar ? 1 : s->nb_channels); plane_size = FFALIGN(plane_size, 16); for (p = 0; p < planes; p++) { s->fdsp->vector_fmac_scalar((float *)out_buf->extended_data[p], (float *) in_buf->extended_data[p], s->input_scale[i], plane_size); } } } av_frame_free(&in_buf); out_buf->pts = s->next_pts; if (s->next_pts != AV_NOPTS_VALUE) s->next_pts += nb_samples; return ff_filter_frame(outlink, out_buf); }
/** * Read samples from the input FIFOs, mix, and write to the output link. */ static int output_frame(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; MixContext *s = ctx->priv; AVFrame *out_buf, *in_buf; int nb_samples, ns, i; if (s->input_state[0] & INPUT_ON) { /* first input live: use the corresponding frame size */ nb_samples = frame_list_next_frame_size(s->frame_list); for (i = 1; i < s->nb_inputs; i++) { if (s->input_state[i] & INPUT_ON) { ns = av_audio_fifo_size(s->fifos[i]); if (ns < nb_samples) { if (!(s->input_state[i] & INPUT_EOF)) /* unclosed input with not enough samples */ return 0; /* closed input to drain */ nb_samples = ns; } } } } else { /* first input closed: use the available samples */ nb_samples = INT_MAX; for (i = 1; i < s->nb_inputs; i++) { if (s->input_state[i] & INPUT_ON) { ns = av_audio_fifo_size(s->fifos[i]); nb_samples = FFMIN(nb_samples, ns); } } if (nb_samples == INT_MAX) { ff_outlink_set_status(outlink, AVERROR_EOF, s->next_pts); return 0; } } s->next_pts = frame_list_next_pts(s->frame_list); frame_list_remove_samples(s->frame_list, nb_samples); calculate_scales(s, nb_samples); if (nb_samples == 0) return 0; out_buf = ff_get_audio_buffer(outlink, nb_samples); if (!out_buf) return AVERROR(ENOMEM); in_buf = ff_get_audio_buffer(outlink, nb_samples); if (!in_buf) { av_frame_free(&out_buf); return AVERROR(ENOMEM); } for (i = 0; i < s->nb_inputs; i++) { if (s->input_state[i] & INPUT_ON) { int planes, plane_size, p; av_audio_fifo_read(s->fifos[i], (void **)in_buf->extended_data, nb_samples); planes = s->planar ? s->nb_channels : 1; plane_size = nb_samples * (s->planar ? 1 : s->nb_channels); plane_size = FFALIGN(plane_size, 16); if (out_buf->format == AV_SAMPLE_FMT_FLT || out_buf->format == AV_SAMPLE_FMT_FLTP) { for (p = 0; p < planes; p++) { s->fdsp->vector_fmac_scalar((float *)out_buf->extended_data[p], (float *) in_buf->extended_data[p], s->input_scale[i], plane_size); } } else { for (p = 0; p < planes; p++) { s->fdsp->vector_dmac_scalar((double *)out_buf->extended_data[p], (double *) in_buf->extended_data[p], s->input_scale[i], plane_size); } } } } av_frame_free(&in_buf); out_buf->pts = s->next_pts; if (s->next_pts != AV_NOPTS_VALUE) s->next_pts += nb_samples; return ff_filter_frame(outlink, out_buf); }