LCOV - code coverage report
Current view: top level - src/libavfilter - af_amix.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 219 271 80.8 %
Date: 2017-07-21 15:41:20 Functions: 15 15 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Audio Mix Filter
       3             :  * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
       4             :  *
       5             :  * This file is part of FFmpeg.
       6             :  *
       7             :  * FFmpeg is free software; you can redistribute it and/or
       8             :  * modify it under the terms of the GNU Lesser General Public
       9             :  * License as published by the Free Software Foundation; either
      10             :  * version 2.1 of the License, or (at your option) any later version.
      11             :  *
      12             :  * FFmpeg is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * Lesser General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU Lesser General Public
      18             :  * License along with FFmpeg; if not, write to the Free Software
      19             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      20             :  */
      21             : 
      22             : /**
      23             :  * @file
      24             :  * Audio Mix Filter
      25             :  *
      26             :  * Mixes audio from multiple sources into a single output. The channel layout,
      27             :  * sample rate, and sample format will be the same for all inputs and the
      28             :  * output.
      29             :  */
      30             : 
      31             : #include "libavutil/attributes.h"
      32             : #include "libavutil/audio_fifo.h"
      33             : #include "libavutil/avassert.h"
      34             : #include "libavutil/avstring.h"
      35             : #include "libavutil/channel_layout.h"
      36             : #include "libavutil/common.h"
      37             : #include "libavutil/float_dsp.h"
      38             : #include "libavutil/mathematics.h"
      39             : #include "libavutil/opt.h"
      40             : #include "libavutil/samplefmt.h"
      41             : 
      42             : #include "audio.h"
      43             : #include "avfilter.h"
      44             : #include "formats.h"
      45             : #include "internal.h"
      46             : 
      47             : #define INPUT_ON       1    /**< input is active */
      48             : #define INPUT_EOF      2    /**< input has reached EOF (may still be active) */
      49             : 
      50             : #define DURATION_LONGEST  0
      51             : #define DURATION_SHORTEST 1
      52             : #define DURATION_FIRST    2
      53             : 
      54             : 
      55             : typedef struct FrameInfo {
      56             :     int nb_samples;
      57             :     int64_t pts;
      58             :     struct FrameInfo *next;
      59             : } FrameInfo;
      60             : 
      61             : /**
      62             :  * Linked list used to store timestamps and frame sizes of all frames in the
      63             :  * FIFO for the first input.
      64             :  *
      65             :  * This is needed to keep timestamps synchronized for the case where multiple
      66             :  * input frames are pushed to the filter for processing before a frame is
      67             :  * requested by the output link.
      68             :  */
      69             : typedef struct FrameList {
      70             :     int nb_frames;
      71             :     int nb_samples;
      72             :     FrameInfo *list;
      73             :     FrameInfo *end;
      74             : } FrameList;
      75             : 
      76         612 : static void frame_list_clear(FrameList *frame_list)
      77             : {
      78         612 :     if (frame_list) {
      79        1823 :         while (frame_list->list) {
      80         605 :             FrameInfo *info = frame_list->list;
      81         605 :             frame_list->list = info->next;
      82         605 :             av_free(info);
      83             :         }
      84         609 :         frame_list->nb_frames  = 0;
      85         609 :         frame_list->nb_samples = 0;
      86         609 :         frame_list->end        = NULL;
      87             :     }
      88         612 : }
      89             : 
      90        2046 : static int frame_list_next_frame_size(FrameList *frame_list)
      91             : {
      92        2046 :     if (!frame_list->list)
      93           1 :         return 0;
      94        2045 :     return frame_list->list->nb_samples;
      95             : }
      96             : 
      97         609 : static int64_t frame_list_next_pts(FrameList *frame_list)
      98             : {
      99         609 :     if (!frame_list->list)
     100           1 :         return AV_NOPTS_VALUE;
     101         608 :     return frame_list->list->pts;
     102             : }
     103             : 
     104         609 : static void frame_list_remove_samples(FrameList *frame_list, int nb_samples)
     105             : {
     106         609 :     if (nb_samples >= frame_list->nb_samples) {
     107         606 :         frame_list_clear(frame_list);
     108             :     } else {
     109           3 :         int samples = nb_samples;
     110           9 :         while (samples > 0) {
     111           3 :             FrameInfo *info = frame_list->list;
     112           3 :             av_assert0(info);
     113           3 :             if (info->nb_samples <= samples) {
     114           0 :                 samples -= info->nb_samples;
     115           0 :                 frame_list->list = info->next;
     116           0 :                 if (!frame_list->list)
     117           0 :                     frame_list->end = NULL;
     118           0 :                 frame_list->nb_frames--;
     119           0 :                 frame_list->nb_samples -= info->nb_samples;
     120           0 :                 av_free(info);
     121             :             } else {
     122           3 :                 info->nb_samples       -= samples;
     123           3 :                 info->pts              += samples;
     124           3 :                 frame_list->nb_samples -= samples;
     125           3 :                 samples = 0;
     126             :             }
     127             :         }
     128             :     }
     129         609 : }
     130             : 
     131         605 : static int frame_list_add_frame(FrameList *frame_list, int nb_samples, int64_t pts)
     132             : {
     133         605 :     FrameInfo *info = av_malloc(sizeof(*info));
     134         605 :     if (!info)
     135           0 :         return AVERROR(ENOMEM);
     136         605 :     info->nb_samples = nb_samples;
     137         605 :     info->pts        = pts;
     138         605 :     info->next       = NULL;
     139             : 
     140         605 :     if (!frame_list->list) {
     141         605 :         frame_list->list = info;
     142         605 :         frame_list->end  = info;
     143             :     } else {
     144           0 :         av_assert0(frame_list->end);
     145           0 :         frame_list->end->next = info;
     146           0 :         frame_list->end       = info;
     147             :     }
     148         605 :     frame_list->nb_frames++;
     149         605 :     frame_list->nb_samples += nb_samples;
     150             : 
     151         605 :     return 0;
     152             : }
     153             : 
     154             : 
     155             : typedef struct MixContext {
     156             :     const AVClass *class;       /**< class for AVOptions */
     157             :     AVFloatDSPContext *fdsp;
     158             : 
     159             :     int nb_inputs;              /**< number of inputs */
     160             :     int active_inputs;          /**< number of input currently active */
     161             :     int duration_mode;          /**< mode for determining duration */
     162             :     float dropout_transition;   /**< transition time when an input drops out */
     163             : 
     164             :     int nb_channels;            /**< number of channels */
     165             :     int sample_rate;            /**< sample rate */
     166             :     int planar;
     167             :     AVAudioFifo **fifos;        /**< audio fifo for each input */
     168             :     uint8_t *input_state;       /**< current state of each input */
     169             :     float *input_scale;         /**< mixing scale factor for each input */
     170             :     float scale_norm;           /**< normalization factor for all inputs */
     171             :     int64_t next_pts;           /**< calculated pts for next output frame */
     172             :     FrameList *frame_list;      /**< list of frame info for the first input */
     173             : } MixContext;
     174             : 
     175             : #define OFFSET(x) offsetof(MixContext, x)
     176             : #define A AV_OPT_FLAG_AUDIO_PARAM
     177             : #define F AV_OPT_FLAG_FILTERING_PARAM
     178             : static const AVOption amix_options[] = {
     179             :     { "inputs", "Number of inputs.",
     180             :             OFFSET(nb_inputs), AV_OPT_TYPE_INT, { .i64 = 2 }, 1, 1024, A|F },
     181             :     { "duration", "How to determine the end-of-stream.",
     182             :             OFFSET(duration_mode), AV_OPT_TYPE_INT, { .i64 = DURATION_LONGEST }, 0,  2, A|F, "duration" },
     183             :         { "longest",  "Duration of longest input.",  0, AV_OPT_TYPE_CONST, { .i64 = DURATION_LONGEST  }, INT_MIN, INT_MAX, A|F, "duration" },
     184             :         { "shortest", "Duration of shortest input.", 0, AV_OPT_TYPE_CONST, { .i64 = DURATION_SHORTEST }, INT_MIN, INT_MAX, A|F, "duration" },
     185             :         { "first",    "Duration of first input.",    0, AV_OPT_TYPE_CONST, { .i64 = DURATION_FIRST    }, INT_MIN, INT_MAX, A|F, "duration" },
     186             :     { "dropout_transition", "Transition time, in seconds, for volume "
     187             :                             "renormalization when an input stream ends.",
     188             :             OFFSET(dropout_transition), AV_OPT_TYPE_FLOAT, { .dbl = 2.0 }, 0, INT_MAX, A|F },
     189             :     { NULL }
     190             : };
     191             : 
     192             : AVFILTER_DEFINE_CLASS(amix);
     193             : 
     194             : /**
     195             :  * Update the scaling factors to apply to each input during mixing.
     196             :  *
     197             :  * This balances the full volume range between active inputs and handles
     198             :  * volume transitions when EOF is encountered on an input but mixing continues
     199             :  * with the remaining inputs.
     200             :  */
     201         612 : static void calculate_scales(MixContext *s, int nb_samples)
     202             : {
     203             :     int i;
     204             : 
     205         612 :     if (s->scale_norm > s->active_inputs) {
     206         131 :         s->scale_norm -= nb_samples / (s->dropout_transition * s->sample_rate);
     207         131 :         s->scale_norm = FFMAX(s->scale_norm, s->active_inputs);
     208             :     }
     209             : 
     210        2098 :     for (i = 0; i < s->nb_inputs; i++) {
     211        1486 :         if (s->input_state[i] & INPUT_ON)
     212        1095 :             s->input_scale[i] = 1.0f / s->scale_norm;
     213             :         else
     214         391 :             s->input_scale[i] = 0.0f;
     215             :     }
     216         612 : }
     217             : 
     218           3 : static int config_output(AVFilterLink *outlink)
     219             : {
     220           3 :     AVFilterContext *ctx = outlink->src;
     221           3 :     MixContext *s      = ctx->priv;
     222             :     int i;
     223             :     char buf[64];
     224             : 
     225           3 :     s->planar          = av_sample_fmt_is_planar(outlink->format);
     226           3 :     s->sample_rate     = outlink->sample_rate;
     227           3 :     outlink->time_base = (AVRational){ 1, outlink->sample_rate };
     228           3 :     s->next_pts        = AV_NOPTS_VALUE;
     229             : 
     230           3 :     s->frame_list = av_mallocz(sizeof(*s->frame_list));
     231           3 :     if (!s->frame_list)
     232           0 :         return AVERROR(ENOMEM);
     233             : 
     234           3 :     s->fifos = av_mallocz_array(s->nb_inputs, sizeof(*s->fifos));
     235           3 :     if (!s->fifos)
     236           0 :         return AVERROR(ENOMEM);
     237             : 
     238           3 :     s->nb_channels = outlink->channels;
     239          10 :     for (i = 0; i < s->nb_inputs; i++) {
     240           7 :         s->fifos[i] = av_audio_fifo_alloc(outlink->format, s->nb_channels, 1024);
     241           7 :         if (!s->fifos[i])
     242           0 :             return AVERROR(ENOMEM);
     243             :     }
     244             : 
     245           3 :     s->input_state = av_malloc(s->nb_inputs);
     246           3 :     if (!s->input_state)
     247           0 :         return AVERROR(ENOMEM);
     248           3 :     memset(s->input_state, INPUT_ON, s->nb_inputs);
     249           3 :     s->active_inputs = s->nb_inputs;
     250             : 
     251           3 :     s->input_scale = av_mallocz_array(s->nb_inputs, sizeof(*s->input_scale));
     252           3 :     if (!s->input_scale)
     253           0 :         return AVERROR(ENOMEM);
     254           3 :     s->scale_norm = s->active_inputs;
     255           3 :     calculate_scales(s, 0);
     256             : 
     257           3 :     av_get_channel_layout_string(buf, sizeof(buf), -1, outlink->channel_layout);
     258             : 
     259           6 :     av_log(ctx, AV_LOG_VERBOSE,
     260             :            "inputs:%d fmt:%s srate:%d cl:%s\n", s->nb_inputs,
     261           3 :            av_get_sample_fmt_name(outlink->format), outlink->sample_rate, buf);
     262             : 
     263           3 :     return 0;
     264             : }
     265             : 
     266             : static int calc_active_inputs(MixContext *s);
     267             : 
     268             : /**
     269             :  * Read samples from the input FIFOs, mix, and write to the output link.
     270             :  */
     271        1567 : static int output_frame(AVFilterLink *outlink, int need_request)
     272             : {
     273        1567 :     AVFilterContext *ctx = outlink->src;
     274        1567 :     MixContext      *s = ctx->priv;
     275             :     AVFrame *out_buf, *in_buf;
     276             :     int nb_samples, ns, ret, i;
     277             : 
     278        1567 :     ret = calc_active_inputs(s);
     279        1567 :     if (ret < 0)
     280           3 :         return ret;
     281             : 
     282        1564 :     if (s->input_state[0] & INPUT_ON) {
     283             :         /* first input live: use the corresponding frame size */
     284        1564 :         nb_samples = frame_list_next_frame_size(s->frame_list);
     285        2609 :         for (i = 1; i < s->nb_inputs; i++) {
     286        2000 :             if (s->input_state[i] & INPUT_ON) {
     287        1609 :                 ns = av_audio_fifo_size(s->fifos[i]);
     288        1609 :                 if (ns < nb_samples) {
     289         958 :                     if (!(s->input_state[i] & INPUT_EOF))
     290             :                         /* unclosed input with not enough samples */
     291         955 :                         return need_request ? ff_request_frame(ctx->inputs[i]) : 0;
     292             :                     /* closed input to drain */
     293           3 :                     nb_samples = ns;
     294             :                 }
     295             :             }
     296             :         }
     297             :     } else {
     298             :         /* first input closed: use the available samples */
     299           0 :         nb_samples = INT_MAX;
     300           0 :         for (i = 1; i < s->nb_inputs; i++) {
     301           0 :             if (s->input_state[i] & INPUT_ON) {
     302           0 :                 ns = av_audio_fifo_size(s->fifos[i]);
     303           0 :                 nb_samples = FFMIN(nb_samples, ns);
     304             :             }
     305             :         }
     306           0 :         if (nb_samples == INT_MAX)
     307           0 :             return AVERROR_EOF;
     308             :     }
     309             : 
     310         609 :     s->next_pts = frame_list_next_pts(s->frame_list);
     311         609 :     frame_list_remove_samples(s->frame_list, nb_samples);
     312             : 
     313         609 :     calculate_scales(s, nb_samples);
     314             : 
     315         609 :     if (nb_samples == 0)
     316           1 :         return 0;
     317             : 
     318         608 :     out_buf = ff_get_audio_buffer(outlink, nb_samples);
     319         608 :     if (!out_buf)
     320           0 :         return AVERROR(ENOMEM);
     321             : 
     322         608 :     in_buf = ff_get_audio_buffer(outlink, nb_samples);
     323         608 :     if (!in_buf) {
     324           0 :         av_frame_free(&out_buf);
     325           0 :         return AVERROR(ENOMEM);
     326             :     }
     327             : 
     328        2085 :     for (i = 0; i < s->nb_inputs; i++) {
     329        1477 :         if (s->input_state[i] & INPUT_ON) {
     330             :             int planes, plane_size, p;
     331             : 
     332        1086 :             av_audio_fifo_read(s->fifos[i], (void **)in_buf->extended_data,
     333             :                                nb_samples);
     334             : 
     335        1086 :             planes     = s->planar ? s->nb_channels : 1;
     336        1086 :             plane_size = nb_samples * (s->planar ? 1 : s->nb_channels);
     337        1086 :             plane_size = FFALIGN(plane_size, 16);
     338             : 
     339        2172 :             if (out_buf->format == AV_SAMPLE_FMT_FLT ||
     340           0 :                 out_buf->format == AV_SAMPLE_FMT_FLTP) {
     341        2172 :                 for (p = 0; p < planes; p++) {
     342        3258 :                     s->fdsp->vector_fmac_scalar((float *)out_buf->extended_data[p],
     343        1086 :                                                 (float *) in_buf->extended_data[p],
     344        1086 :                                                 s->input_scale[i], plane_size);
     345             :                 }
     346             :             } else {
     347           0 :                 for (p = 0; p < planes; p++) {
     348           0 :                     s->fdsp->vector_dmac_scalar((double *)out_buf->extended_data[p],
     349           0 :                                                 (double *) in_buf->extended_data[p],
     350           0 :                                                 s->input_scale[i], plane_size);
     351             :                 }
     352             :             }
     353             :         }
     354             :     }
     355         608 :     av_frame_free(&in_buf);
     356             : 
     357         608 :     out_buf->pts = s->next_pts;
     358         608 :     if (s->next_pts != AV_NOPTS_VALUE)
     359         608 :         s->next_pts += nb_samples;
     360             : 
     361         608 :     return ff_filter_frame(outlink, out_buf);
     362             : }
     363             : 
     364             : /**
     365             :  * Requests a frame, if needed, from each input link other than the first.
     366             :  */
     367         482 : static int request_samples(AVFilterContext *ctx, int min_samples)
     368             : {
     369         482 :     MixContext *s = ctx->priv;
     370             :     int i, ret;
     371             : 
     372         482 :     av_assert0(s->nb_inputs > 1);
     373             : 
     374        1228 :     for (i = 1; i < s->nb_inputs; i++) {
     375         746 :         ret = 0;
     376         746 :         if (!(s->input_state[i] & INPUT_ON))
     377          89 :             continue;
     378         657 :         if (av_audio_fifo_size(s->fifos[i]) >= min_samples)
     379          89 :             continue;
     380         568 :         ret = ff_request_frame(ctx->inputs[i]);
     381         568 :         if (ret == AVERROR_EOF) {
     382           6 :             s->input_state[i] |= INPUT_EOF;
     383           6 :             if (av_audio_fifo_size(s->fifos[i]) == 0) {
     384           3 :                 s->input_state[i] = 0;
     385           3 :                 continue;
     386             :             }
     387         562 :         } else if (ret < 0)
     388           0 :             return ret;
     389             :     }
     390         482 :     return output_frame(ctx->outputs[0], 1);
     391             : }
     392             : 
     393             : /**
     394             :  * Calculates the number of active inputs and determines EOF based on the
     395             :  * duration option.
     396             :  *
     397             :  * @return 0 if mixing should continue, or AVERROR_EOF if mixing should stop.
     398             :  */
     399        2657 : static int calc_active_inputs(MixContext *s)
     400             : {
     401             :     int i;
     402        2657 :     int active_inputs = 0;
     403        9279 :     for (i = 0; i < s->nb_inputs; i++)
     404        6622 :         active_inputs += !!(s->input_state[i] & INPUT_ON);
     405        2657 :     s->active_inputs = active_inputs;
     406             : 
     407        5312 :     if (!active_inputs ||
     408        5744 :         (s->duration_mode == DURATION_FIRST && !(s->input_state[0] & INPUT_ON)) ||
     409        2654 :         (s->duration_mode == DURATION_SHORTEST && active_inputs != s->nb_inputs))
     410           3 :         return AVERROR_EOF;
     411        2654 :     return 0;
     412             : }
     413             : 
     414        1090 : static int request_frame(AVFilterLink *outlink)
     415             : {
     416        1090 :     AVFilterContext *ctx = outlink->src;
     417        1090 :     MixContext      *s = ctx->priv;
     418             :     int ret;
     419             :     int wanted_samples;
     420             : 
     421        1090 :     ret = calc_active_inputs(s);
     422        1090 :     if (ret < 0)
     423           0 :         return ret;
     424             : 
     425        1090 :     if (!(s->input_state[0] & INPUT_ON))
     426           0 :         return request_samples(ctx, 1);
     427             : 
     428        1090 :     if (s->frame_list->nb_frames == 0) {
     429         608 :         ret = ff_request_frame(ctx->inputs[0]);
     430         608 :         if (ret == AVERROR_EOF) {
     431           3 :             s->input_state[0] = 0;
     432           3 :             if (s->nb_inputs == 1)
     433           0 :                 return AVERROR_EOF;
     434           3 :             return output_frame(ctx->outputs[0], 1);
     435             :         }
     436         605 :         return ret;
     437             :     }
     438         482 :     av_assert0(s->frame_list->nb_frames > 0);
     439             : 
     440         482 :     wanted_samples = frame_list_next_frame_size(s->frame_list);
     441             : 
     442         482 :     return request_samples(ctx, wanted_samples);
     443             : }
     444             : 
     445        1082 : static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
     446             : {
     447        1082 :     AVFilterContext  *ctx = inlink->dst;
     448        1082 :     MixContext       *s = ctx->priv;
     449        1082 :     AVFilterLink *outlink = ctx->outputs[0];
     450        1082 :     int i, ret = 0;
     451             : 
     452        1646 :     for (i = 0; i < ctx->nb_inputs; i++)
     453        1646 :         if (ctx->inputs[i] == inlink)
     454        1082 :             break;
     455        1082 :     if (i >= ctx->nb_inputs) {
     456           0 :         av_log(ctx, AV_LOG_ERROR, "unknown input link\n");
     457           0 :         ret = AVERROR(EINVAL);
     458           0 :         goto fail;
     459             :     }
     460             : 
     461        1082 :     if (i == 0) {
     462         605 :         int64_t pts = av_rescale_q(buf->pts, inlink->time_base,
     463             :                                    outlink->time_base);
     464         605 :         ret = frame_list_add_frame(s->frame_list, buf->nb_samples, pts);
     465         605 :         if (ret < 0)
     466           0 :             goto fail;
     467             :     }
     468             : 
     469        1082 :     ret = av_audio_fifo_write(s->fifos[i], (void **)buf->extended_data,
     470        1082 :                               buf->nb_samples);
     471        1082 :     if (ret < 0)
     472           0 :         goto fail;
     473             : 
     474        1082 :     av_frame_free(&buf);
     475        1082 :     return output_frame(outlink, 0);
     476             : 
     477           0 : fail:
     478           0 :     av_frame_free(&buf);
     479             : 
     480           0 :     return ret;
     481             : }
     482             : 
     483           6 : static av_cold int init(AVFilterContext *ctx)
     484             : {
     485           6 :     MixContext *s = ctx->priv;
     486             :     int i;
     487             : 
     488          20 :     for (i = 0; i < s->nb_inputs; i++) {
     489             :         char name[32];
     490          14 :         AVFilterPad pad = { 0 };
     491             : 
     492          14 :         snprintf(name, sizeof(name), "input%d", i);
     493          14 :         pad.type           = AVMEDIA_TYPE_AUDIO;
     494          14 :         pad.name           = av_strdup(name);
     495          14 :         if (!pad.name)
     496           0 :             return AVERROR(ENOMEM);
     497          14 :         pad.filter_frame   = filter_frame;
     498             : 
     499          14 :         ff_insert_inpad(ctx, i, &pad);
     500             :     }
     501             : 
     502           6 :     s->fdsp = avpriv_float_dsp_alloc(0);
     503           6 :     if (!s->fdsp)
     504           0 :         return AVERROR(ENOMEM);
     505             : 
     506           6 :     return 0;
     507             : }
     508             : 
     509           6 : static av_cold void uninit(AVFilterContext *ctx)
     510             : {
     511             :     int i;
     512           6 :     MixContext *s = ctx->priv;
     513             : 
     514           6 :     if (s->fifos) {
     515          10 :         for (i = 0; i < s->nb_inputs; i++)
     516           7 :             av_audio_fifo_free(s->fifos[i]);
     517           3 :         av_freep(&s->fifos);
     518             :     }
     519           6 :     frame_list_clear(s->frame_list);
     520           6 :     av_freep(&s->frame_list);
     521           6 :     av_freep(&s->input_state);
     522           6 :     av_freep(&s->input_scale);
     523           6 :     av_freep(&s->fdsp);
     524             : 
     525          20 :     for (i = 0; i < ctx->nb_inputs; i++)
     526          14 :         av_freep(&ctx->input_pads[i].name);
     527           6 : }
     528             : 
     529           3 : static int query_formats(AVFilterContext *ctx)
     530             : {
     531           3 :     AVFilterFormats *formats = NULL;
     532             :     AVFilterChannelLayouts *layouts;
     533             :     int ret;
     534             : 
     535           3 :     layouts = ff_all_channel_counts();
     536           3 :     if (!layouts) {
     537           0 :         ret = AVERROR(ENOMEM);
     538           0 :         goto fail;
     539             :     }
     540             : 
     541           3 :     if ((ret = ff_add_format(&formats, AV_SAMPLE_FMT_FLT ))          < 0 ||
     542           3 :         (ret = ff_add_format(&formats, AV_SAMPLE_FMT_FLTP))          < 0 ||
     543           3 :         (ret = ff_add_format(&formats, AV_SAMPLE_FMT_DBL ))          < 0 ||
     544           3 :         (ret = ff_add_format(&formats, AV_SAMPLE_FMT_DBLP))          < 0 ||
     545           6 :         (ret = ff_set_common_formats        (ctx, formats))          < 0 ||
     546           6 :         (ret = ff_set_common_channel_layouts(ctx, layouts))          < 0 ||
     547           3 :         (ret = ff_set_common_samplerates(ctx, ff_all_samplerates())) < 0)
     548             :         goto fail;
     549           3 :     return 0;
     550           0 : fail:
     551           0 :     if (layouts)
     552           0 :         av_freep(&layouts->channel_layouts);
     553           0 :     av_freep(&layouts);
     554           0 :     return ret;
     555             : }
     556             : 
     557             : static const AVFilterPad avfilter_af_amix_outputs[] = {
     558             :     {
     559             :         .name          = "default",
     560             :         .type          = AVMEDIA_TYPE_AUDIO,
     561             :         .config_props  = config_output,
     562             :         .request_frame = request_frame
     563             :     },
     564             :     { NULL }
     565             : };
     566             : 
     567             : AVFilter ff_af_amix = {
     568             :     .name           = "amix",
     569             :     .description    = NULL_IF_CONFIG_SMALL("Audio mixing."),
     570             :     .priv_size      = sizeof(MixContext),
     571             :     .priv_class     = &amix_class,
     572             :     .init           = init,
     573             :     .uninit         = uninit,
     574             :     .query_formats  = query_formats,
     575             :     .inputs         = NULL,
     576             :     .outputs        = avfilter_af_amix_outputs,
     577             :     .flags          = AVFILTER_FLAG_DYNAMIC_INPUTS,
     578             : };

Generated by: LCOV version 1.13