LCOV - code coverage report
Current view: top level - libavfilter - af_adelay.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 82 103 79.6 %
Date: 2017-12-15 18:13:28 Functions: 6 10 60.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Paul B Mahol
       3             :  *
       4             :  * This file is part of FFmpeg.
       5             :  *
       6             :  * FFmpeg is free software; you can redistribute it and/or
       7             :  * modify it under the terms of the GNU Lesser General Public
       8             :  * License as published by the Free Software Foundation; either
       9             :  * version 2.1 of the License, or (at your option) any later version.
      10             :  *
      11             :  * FFmpeg is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * Lesser General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU Lesser General Public
      17             :  * License along with FFmpeg; if not, write to the Free Software
      18             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : 
      21             : #include "libavutil/avstring.h"
      22             : #include "libavutil/opt.h"
      23             : #include "libavutil/samplefmt.h"
      24             : #include "avfilter.h"
      25             : #include "audio.h"
      26             : #include "internal.h"
      27             : 
      28             : typedef struct ChanDelay {
      29             :     int delay;
      30             :     unsigned delay_index;
      31             :     unsigned index;
      32             :     uint8_t *samples;
      33             : } ChanDelay;
      34             : 
      35             : typedef struct AudioDelayContext {
      36             :     const AVClass *class;
      37             :     char *delays;
      38             :     ChanDelay *chandelay;
      39             :     int nb_delays;
      40             :     int block_align;
      41             :     unsigned max_delay;
      42             :     int64_t next_pts;
      43             : 
      44             :     void (*delay_channel)(ChanDelay *d, int nb_samples,
      45             :                           const uint8_t *src, uint8_t *dst);
      46             : } AudioDelayContext;
      47             : 
      48             : #define OFFSET(x) offsetof(AudioDelayContext, x)
      49             : #define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
      50             : 
      51             : static const AVOption adelay_options[] = {
      52             :     { "delays", "set list of delays for each channel", OFFSET(delays), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, A },
      53             :     { NULL }
      54             : };
      55             : 
      56             : AVFILTER_DEFINE_CLASS(adelay);
      57             : 
      58           1 : static int query_formats(AVFilterContext *ctx)
      59             : {
      60             :     AVFilterChannelLayouts *layouts;
      61             :     AVFilterFormats *formats;
      62             :     static const enum AVSampleFormat sample_fmts[] = {
      63             :         AV_SAMPLE_FMT_U8P, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P,
      64             :         AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBLP,
      65             :         AV_SAMPLE_FMT_NONE
      66             :     };
      67             :     int ret;
      68             : 
      69           1 :     layouts = ff_all_channel_counts();
      70           1 :     if (!layouts)
      71           0 :         return AVERROR(ENOMEM);
      72           1 :     ret = ff_set_common_channel_layouts(ctx, layouts);
      73           1 :     if (ret < 0)
      74           0 :         return ret;
      75             : 
      76           1 :     formats = ff_make_format_list(sample_fmts);
      77           1 :     if (!formats)
      78           0 :         return AVERROR(ENOMEM);
      79           1 :     ret = ff_set_common_formats(ctx, formats);
      80           1 :     if (ret < 0)
      81           0 :         return ret;
      82             : 
      83           1 :     formats = ff_all_samplerates();
      84           1 :     if (!formats)
      85           0 :         return AVERROR(ENOMEM);
      86           1 :     return ff_set_common_samplerates(ctx, formats);
      87             : }
      88             : 
      89             : #define DELAY(name, type, fill)                                           \
      90             : static void delay_channel_## name ##p(ChanDelay *d, int nb_samples,       \
      91             :                                       const uint8_t *ssrc, uint8_t *ddst) \
      92             : {                                                                         \
      93             :     const type *src = (type *)ssrc;                                       \
      94             :     type *dst = (type *)ddst;                                             \
      95             :     type *samples = (type *)d->samples;                                   \
      96             :                                                                           \
      97             :     while (nb_samples) {                                                  \
      98             :         if (d->delay_index < d->delay) {                                  \
      99             :             const int len = FFMIN(nb_samples, d->delay - d->delay_index); \
     100             :                                                                           \
     101             :             memcpy(&samples[d->delay_index], src, len * sizeof(type));    \
     102             :             memset(dst, fill, len * sizeof(type));                        \
     103             :             d->delay_index += len;                                        \
     104             :             src += len;                                                   \
     105             :             dst += len;                                                   \
     106             :             nb_samples -= len;                                            \
     107             :         } else {                                                          \
     108             :             *dst = samples[d->index];                                     \
     109             :             samples[d->index] = *src;                                     \
     110             :             nb_samples--;                                                 \
     111             :             d->index++;                                                   \
     112             :             src++, dst++;                                                 \
     113             :             d->index = d->index >= d->delay ? 0 : d->index;               \
     114             :         }                                                                 \
     115             :     }                                                                     \
     116             : }
     117             : 
     118           0 : DELAY(u8,  uint8_t, 0x80)
     119         260 : DELAY(s16, int16_t, 0)
     120           0 : DELAY(s32, int32_t, 0)
     121           0 : DELAY(flt, float,   0)
     122           0 : DELAY(dbl, double,  0)
     123             : 
     124           1 : static int config_input(AVFilterLink *inlink)
     125             : {
     126           1 :     AVFilterContext *ctx = inlink->dst;
     127           1 :     AudioDelayContext *s = ctx->priv;
     128           1 :     char *p, *arg, *saveptr = NULL;
     129             :     int i;
     130             : 
     131           1 :     s->chandelay = av_calloc(inlink->channels, sizeof(*s->chandelay));
     132           1 :     if (!s->chandelay)
     133           0 :         return AVERROR(ENOMEM);
     134           1 :     s->nb_delays = inlink->channels;
     135           1 :     s->block_align = av_get_bytes_per_sample(inlink->format);
     136             : 
     137           1 :     p = s->delays;
     138           2 :     for (i = 0; i < s->nb_delays; i++) {
     139           2 :         ChanDelay *d = &s->chandelay[i];
     140             :         float delay;
     141           2 :         char type = 0;
     142             :         int ret;
     143             : 
     144           2 :         if (!(arg = av_strtok(p, "|", &saveptr)))
     145           1 :             break;
     146             : 
     147           1 :         p = NULL;
     148             : 
     149           1 :         ret = sscanf(arg, "%d%c", &d->delay, &type);
     150           1 :         if (ret != 2 || type != 'S') {
     151           1 :             sscanf(arg, "%f", &delay);
     152           1 :             d->delay = delay * inlink->sample_rate / 1000.0;
     153             :         }
     154             : 
     155           1 :         if (d->delay < 0) {
     156           0 :             av_log(ctx, AV_LOG_ERROR, "Delay must be non negative number.\n");
     157           0 :             return AVERROR(EINVAL);
     158             :         }
     159             :     }
     160             : 
     161           3 :     for (i = 0; i < s->nb_delays; i++) {
     162           2 :         ChanDelay *d = &s->chandelay[i];
     163             : 
     164           2 :         if (!d->delay)
     165           1 :             continue;
     166             : 
     167           1 :         d->samples = av_malloc_array(d->delay, s->block_align);
     168           1 :         if (!d->samples)
     169           0 :             return AVERROR(ENOMEM);
     170             : 
     171           1 :         s->max_delay = FFMAX(s->max_delay, d->delay);
     172             :     }
     173             : 
     174           1 :     switch (inlink->format) {
     175           0 :     case AV_SAMPLE_FMT_U8P : s->delay_channel = delay_channel_u8p ; break;
     176           1 :     case AV_SAMPLE_FMT_S16P: s->delay_channel = delay_channel_s16p; break;
     177           0 :     case AV_SAMPLE_FMT_S32P: s->delay_channel = delay_channel_s32p; break;
     178           0 :     case AV_SAMPLE_FMT_FLTP: s->delay_channel = delay_channel_fltp; break;
     179           0 :     case AV_SAMPLE_FMT_DBLP: s->delay_channel = delay_channel_dblp; break;
     180             :     }
     181             : 
     182           1 :     return 0;
     183             : }
     184             : 
     185         260 : static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
     186             : {
     187         260 :     AVFilterContext *ctx = inlink->dst;
     188         260 :     AudioDelayContext *s = ctx->priv;
     189             :     AVFrame *out_frame;
     190             :     int i;
     191             : 
     192         260 :     if (ctx->is_disabled || !s->delays)
     193           0 :         return ff_filter_frame(ctx->outputs[0], frame);
     194             : 
     195         260 :     out_frame = ff_get_audio_buffer(inlink, frame->nb_samples);
     196         260 :     if (!out_frame) {
     197           0 :         av_frame_free(&frame);
     198           0 :         return AVERROR(ENOMEM);
     199             :     }
     200         260 :     av_frame_copy_props(out_frame, frame);
     201             : 
     202         780 :     for (i = 0; i < s->nb_delays; i++) {
     203         520 :         ChanDelay *d = &s->chandelay[i];
     204         520 :         const uint8_t *src = frame->extended_data[i];
     205         520 :         uint8_t *dst = out_frame->extended_data[i];
     206             : 
     207         520 :         if (!d->delay)
     208         260 :             memcpy(dst, src, frame->nb_samples * s->block_align);
     209             :         else
     210         260 :             s->delay_channel(d, frame->nb_samples, src, dst);
     211             :     }
     212             : 
     213         260 :     s->next_pts = frame->pts + av_rescale_q(frame->nb_samples, (AVRational){1, inlink->sample_rate}, inlink->time_base);
     214         260 :     av_frame_free(&frame);
     215         260 :     return ff_filter_frame(ctx->outputs[0], out_frame);
     216             : }
     217             : 
     218         261 : static int request_frame(AVFilterLink *outlink)
     219             : {
     220         261 :     AVFilterContext *ctx = outlink->src;
     221         261 :     AudioDelayContext *s = ctx->priv;
     222             :     int ret;
     223             : 
     224         261 :     ret = ff_request_frame(ctx->inputs[0]);
     225         261 :     if (ret == AVERROR_EOF && !ctx->is_disabled && s->max_delay) {
     226           1 :         int nb_samples = FFMIN(s->max_delay, 2048);
     227             :         AVFrame *frame;
     228             : 
     229           1 :         frame = ff_get_audio_buffer(outlink, nb_samples);
     230           1 :         if (!frame)
     231           0 :             return AVERROR(ENOMEM);
     232           1 :         s->max_delay -= nb_samples;
     233             : 
     234           1 :         av_samples_set_silence(frame->extended_data, 0,
     235             :                                frame->nb_samples,
     236             :                                outlink->channels,
     237           1 :                                frame->format);
     238             : 
     239           1 :         frame->pts = s->next_pts;
     240           1 :         if (s->next_pts != AV_NOPTS_VALUE)
     241           1 :             s->next_pts += av_rescale_q(nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base);
     242             : 
     243           1 :         ret = filter_frame(ctx->inputs[0], frame);
     244             :     }
     245             : 
     246         261 :     return ret;
     247             : }
     248             : 
     249           1 : static av_cold void uninit(AVFilterContext *ctx)
     250             : {
     251           1 :     AudioDelayContext *s = ctx->priv;
     252             :     int i;
     253             : 
     254           3 :     for (i = 0; i < s->nb_delays; i++)
     255           2 :         av_freep(&s->chandelay[i].samples);
     256           1 :     av_freep(&s->chandelay);
     257           1 : }
     258             : 
     259             : static const AVFilterPad adelay_inputs[] = {
     260             :     {
     261             :         .name         = "default",
     262             :         .type         = AVMEDIA_TYPE_AUDIO,
     263             :         .config_props = config_input,
     264             :         .filter_frame = filter_frame,
     265             :     },
     266             :     { NULL }
     267             : };
     268             : 
     269             : static const AVFilterPad adelay_outputs[] = {
     270             :     {
     271             :         .name          = "default",
     272             :         .request_frame = request_frame,
     273             :         .type          = AVMEDIA_TYPE_AUDIO,
     274             :     },
     275             :     { NULL }
     276             : };
     277             : 
     278             : AVFilter ff_af_adelay = {
     279             :     .name          = "adelay",
     280             :     .description   = NULL_IF_CONFIG_SMALL("Delay one or more audio channels."),
     281             :     .query_formats = query_formats,
     282             :     .priv_size     = sizeof(AudioDelayContext),
     283             :     .priv_class    = &adelay_class,
     284             :     .uninit        = uninit,
     285             :     .inputs        = adelay_inputs,
     286             :     .outputs       = adelay_outputs,
     287             :     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
     288             : };

Generated by: LCOV version 1.13