]> git.sesse.net Git - ffmpeg/blobdiff - libavfilter/af_amix.c
nut: add 12/14 bit yuv to nut/raw
[ffmpeg] / libavfilter / af_amix.c
index 81586981be87c1250a5bfc5340c3eaf9b248357d..e70c6b6f0858b02bc323226de240973441b748db 100644 (file)
@@ -32,6 +32,7 @@
 #include "libavutil/audio_fifo.h"
 #include "libavutil/avassert.h"
 #include "libavutil/avstring.h"
+#include "libavutil/float_dsp.h"
 #include "libavutil/mathematics.h"
 #include "libavutil/opt.h"
 #include "libavutil/samplefmt.h"
@@ -152,6 +153,7 @@ static int frame_list_add_frame(FrameList *frame_list, int nb_samples, int64_t p
 
 typedef struct MixContext {
     const AVClass *class;       /**< class for AVOptions */
+    AVFloatDSPContext fdsp;
 
     int nb_inputs;              /**< number of inputs */
     int active_inputs;          /**< number of input currently active */
@@ -160,6 +162,7 @@ typedef struct MixContext {
 
     int nb_channels;            /**< number of channels */
     int sample_rate;            /**< sample rate */
+    int planar;
     AVAudioFifo **fifos;        /**< audio fifo for each input */
     uint8_t *input_state;       /**< current state of each input */
     float *input_scale;         /**< mixing scale factor for each input */
@@ -170,7 +173,7 @@ typedef struct MixContext {
 
 #define OFFSET(x) offsetof(MixContext, x)
 #define A AV_OPT_FLAG_AUDIO_PARAM
-static const AVOption options[] = {
+static const AVOption amix_options[] = {
     { "inputs", "Number of inputs.",
             OFFSET(nb_inputs), AV_OPT_TYPE_INT, { 2 }, 1, 32, A },
     { "duration", "How to determine the end-of-stream.",
@@ -184,14 +187,7 @@ static const AVOption options[] = {
     { NULL },
 };
 
-static const AVClass amix_class = {
-    .class_name = "amix",
-    .item_name  = av_default_item_name,
-    .option     = options,
-    .version    = LIBAVUTIL_VERSION_INT,
-    .category   = AV_CLASS_CATEGORY_FILTER,
-};
-
+AVFILTER_DEFINE_CLASS(amix);
 
 /**
  * Update the scaling factors to apply to each input during mixing.
@@ -224,6 +220,7 @@ static int config_output(AVFilterLink *outlink)
     int i;
     char buf[64];
 
+    s->planar          = av_sample_fmt_is_planar(outlink->format);
     s->sample_rate     = outlink->sample_rate;
     outlink->time_base = (AVRational){ 1, outlink->sample_rate };
     s->next_pts        = AV_NOPTS_VALUE;
@@ -258,20 +255,12 @@ static int config_output(AVFilterLink *outlink)
     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;
 }
 
-/* TODO: move optimized version from DSPContext to libavutil */
-static void vector_fmac_scalar(float *dst, const float *src, float mul, int len)
-{
-    int i;
-    for (i = 0; i < len; i++)
-        dst[i] += src[i] * mul;
-}
-
 /**
  * Read samples from the input FIFOs, mix, and write to the output link.
  */
@@ -294,11 +283,20 @@ static int output_frame(AVFilterLink *outlink, int nb_samples)
 
     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);
-            vector_fmac_scalar((float *)out_buf->extended_data[0],
-                               (float *) in_buf->extended_data[0],
-                               s->input_scale[i], nb_samples * s->nb_channels);
+
+            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);
+            }
         }
     }
     avfilter_unref_buffer(in_buf);
@@ -475,7 +473,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
     avfilter_unref_buffer(buf);
 }
 
-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;
@@ -501,6 +499,8 @@ static int init(AVFilterContext *ctx, const char *args, void *opaque)
         ff_insert_inpad(ctx, i, &pad);
     }
 
+    avpriv_float_dsp_init(&s->fdsp, 0);
+
     return 0;
 }
 
@@ -527,6 +527,7 @@ static int query_formats(AVFilterContext *ctx)
 {
     AVFilterFormats *formats = NULL;
     ff_add_format(&formats, AV_SAMPLE_FMT_FLT);
+    ff_add_format(&formats, AV_SAMPLE_FMT_FLTP);
     ff_set_common_formats(ctx, formats);
     ff_set_common_channel_layouts(ctx, ff_all_channel_layouts());
     ff_set_common_samplerates(ctx, ff_all_samplerates());