Advertisement
Guest User

adelay.c with commands

a guest
Jan 18th, 2022
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 16.51 KB | None | 0 0
  1. #include "libavutil/avstring.h"
  2. #include "libavutil/eval.h"
  3. #include "libavutil/opt.h"
  4. #include "libavutil/samplefmt.h"
  5. #include "avfilter.h"
  6. #include "audio.h"
  7. #include "filters.h"
  8. #include "internal.h"
  9.  
  10. typedef struct ChanDelay {
  11.     int64_t delay;
  12.     size_t delay_index;
  13.     size_t index;
  14.     unsigned int samples_size;
  15.     uint8_t *samples;
  16. } ChanDelay;
  17.  
  18. typedef struct AudioDelayContext {
  19.     const AVClass *class;
  20.     int all;
  21.     char *delays;
  22.     ChanDelay *chandelay;
  23.     int nb_delays;
  24.     int block_align;
  25.     int64_t padding;
  26.     int64_t max_delay;
  27.     int64_t next_pts;
  28.     int eof;
  29.  
  30.     void (*delay_channel)(ChanDelay *d, int nb_samples,
  31.                           const uint8_t *src, uint8_t *dst);
  32.     int (*resize_channel_samples)(ChanDelay *d, int64_t new_delay);
  33. } AudioDelayContext;
  34.  
  35. #define OFFSET(x) offsetof(AudioDelayContext, x)
  36. #define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
  37.  
  38. static const AVOption adelay_options[] = {
  39.     { "delays", "set list of delays for each channel", OFFSET(delays), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, A | AV_OPT_FLAG_RUNTIME_PARAM },
  40.     { "all",    "use last available delay for remained channels", OFFSET(all), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, A },
  41.     { NULL }
  42. };
  43.  
  44. AVFILTER_DEFINE_CLASS(adelay);
  45.  
  46. #define DELAY(name, type, fill)                                           \
  47. static void delay_channel_## name ##p(ChanDelay *d, int nb_samples,       \
  48.                                       const uint8_t *ssrc, uint8_t *ddst) \
  49. {                                                                         \
  50.     const type *src = (type *)ssrc;                                       \
  51.     type *dst = (type *)ddst;                                             \
  52.     type *samples = (type *)d->samples;                                   \
  53.                                                                           \
  54.     while (nb_samples) {                                                  \
  55.         if (d->delay_index < d->delay) {                                  \
  56.             const int len = FFMIN(nb_samples, d->delay - d->delay_index); \
  57.                                                                           \
  58.             memcpy(&samples[d->delay_index], src, len * sizeof(type));    \
  59.             memset(dst, fill, len * sizeof(type));                        \
  60.             d->delay_index += len;                                        \
  61.             src += len;                                                   \
  62.             dst += len;                                                   \
  63.             nb_samples -= len;                                            \
  64.         } else {                                                          \
  65.             *dst = samples[d->index];                                     \
  66.             samples[d->index] = *src;                                     \
  67.             nb_samples--;                                                 \
  68.             d->index++;                                                   \
  69.             src++, dst++;                                                 \
  70.             d->index = d->index >= d->delay ? 0 : d->index;               \
  71.         }                                                                 \
  72.     }                                                                     \
  73. }
  74.  
  75. DELAY(u8,  uint8_t, 0x80)
  76. DELAY(s16, int16_t, 0)
  77. DELAY(s32, int32_t, 0)
  78. DELAY(flt, float,   0)
  79. DELAY(dbl, double,  0)
  80.  
  81. #define CHANGE_DELAY(name, type, fill)                                                                  \
  82. static int resize_samples_## name ##p(ChanDelay *d, int64_t new_delay)                                  \
  83. {                                                                                                       \
  84.     type *samples = (type *)d->samples;                                                                 \
  85.                                                                                                         \
  86.     if (new_delay == 0) {                                                                               \
  87.         av_freep(&d->samples);                                                                          \
  88.         d->samples_size = 0;                                                                            \
  89.         d->delay = 0;                                                                                   \
  90.         d->index = 0;                                                                                   \
  91.         return 0;                                                                                       \
  92.     }                                                                                                   \
  93.                                                                                                         \
  94.     d->samples = av_fast_realloc(d->samples, &d->samples_size, new_delay * sizeof(type));               \
  95.     if (!d->samples) {                                                                                  \
  96.         av_freep(samples);                                                                              \
  97.         return AVERROR(ENOMEM);                                                                         \
  98.     }                                                                                                   \
  99.     samples = (type *)d->samples;                                                                       \
  100.     if (new_delay < d->delay) {                                                                         \
  101.         if (d->index > new_delay) {                                                                     \
  102.             d->index -= new_delay;                                                                      \
  103.             memmove(samples, &samples[new_delay], d->index * sizeof(type));                             \
  104.         } else if (d->delay_index > d->index) {                                                         \
  105.             memmove(&samples[d->index], &samples[d->index+(d->delay-new_delay)],                        \
  106.                     (new_delay - d->index) * sizeof(type));                                             \
  107.         }                                                                                               \
  108.         d->delay_index = new_delay;                                                                     \
  109.     } else {                                                                                            \
  110.         size_t block_size;                                                                              \
  111.         if (d->delay_index >= d->delay) {                                                               \
  112.             block_size = (d->delay - d->index) * sizeof(type);                                          \
  113.             memmove(&samples[d->index+(new_delay - d->delay)], &samples[d->index], block_size);         \
  114.             d->delay_index = new_delay;                                                                 \
  115.         } else {                                                                                        \
  116.             d->delay_index += new_delay - d->delay;                                                     \
  117.         }                                                                                               \
  118.         block_size = (new_delay - d->delay) * sizeof(type);                                             \
  119.         memset(&samples[d->index], fill, block_size);                                                   \
  120.     }                                                                                                   \
  121.     d->delay = new_delay;                                                                               \
  122.     d->samples = (void *) samples;                                                                      \
  123.     return 0;                                                                                           \
  124. }
  125.  
  126. CHANGE_DELAY(u8,  uint8_t, 0x80)
  127. CHANGE_DELAY(s16, int16_t, 0)
  128. CHANGE_DELAY(s32, int32_t, 0)
  129. CHANGE_DELAY(flt, float,   0)
  130. CHANGE_DELAY(dbl, double,  0)
  131.  
  132. static int config_input(AVFilterLink *inlink)
  133. {
  134.     AVFilterContext *ctx = inlink->dst;
  135.     AudioDelayContext *s = ctx->priv;
  136.     char *p, *arg, *saveptr = NULL;
  137.     int i;
  138.  
  139.     s->chandelay = av_calloc(inlink->channels, sizeof(*s->chandelay));
  140.     if (!s->chandelay)
  141.         return AVERROR(ENOMEM);
  142.     s->nb_delays = inlink->channels;
  143.     s->block_align = av_get_bytes_per_sample(inlink->format);
  144.  
  145.     p = s->delays;
  146.     for (i = 0; i < s->nb_delays; i++) {
  147.         ChanDelay *d = &s->chandelay[i];
  148.         float delay, div;
  149.         char type = 0;
  150.         int ret;
  151.  
  152.         if (!(arg = av_strtok(p, "|", &saveptr)))
  153.             break;
  154.  
  155.         p = NULL;
  156.  
  157.         ret = av_sscanf(arg, "%"SCNd64"%c", &d->delay, &type);
  158.         if (ret != 2 || type != 'S') {
  159.             div = type == 's' ? 1.0 : 1000.0;
  160.             if (av_sscanf(arg, "%f", &delay) != 1) {
  161.                 av_log(ctx, AV_LOG_ERROR, "Invalid syntax for delay.\n");
  162.                 return AVERROR(EINVAL);
  163.             }
  164.             d->delay = delay * inlink->sample_rate / div;
  165.         }
  166.  
  167.         if (d->delay < 0) {
  168.             av_log(ctx, AV_LOG_ERROR, "Delay must be non negative number.\n");
  169.             return AVERROR(EINVAL);
  170.         }
  171.     }
  172.  
  173.     if (s->all && i) {
  174.         for (int j = i; j < s->nb_delays; j++)
  175.             s->chandelay[j].delay = s->chandelay[i-1].delay;
  176.     }
  177.  
  178.     s->padding = s->chandelay[0].delay;
  179.     for (i = 1; i < s->nb_delays; i++) {
  180.         ChanDelay *d = &s->chandelay[i];
  181.  
  182.         s->padding = FFMIN(s->padding, d->delay);
  183.     }
  184.  
  185.     if (s->padding) {
  186.         for (i = 0; i < s->nb_delays; i++) {
  187.             ChanDelay *d = &s->chandelay[i];
  188.  
  189.             d->delay -= s->padding;
  190.         }
  191.     }
  192.  
  193.     for (i = 0; i < s->nb_delays; i++) {
  194.         ChanDelay *d = &s->chandelay[i];
  195.  
  196.         if (!d->delay)
  197.             continue;
  198.  
  199.         if (d->delay > SIZE_MAX) {
  200.             av_log(ctx, AV_LOG_ERROR, "Requested delay is too big.\n");
  201.             return AVERROR(EINVAL);
  202.         }
  203.  
  204.         d->samples = av_malloc_array(d->delay, s->block_align);
  205.         if (!d->samples)
  206.             return AVERROR(ENOMEM);
  207.         d->samples_size = d->delay * s->block_align;
  208.  
  209.         s->max_delay = FFMAX(s->max_delay, d->delay);
  210.     }
  211.  
  212.     switch (inlink->format) {
  213.     case AV_SAMPLE_FMT_U8P : s->delay_channel = delay_channel_u8p ;
  214.                              s->resize_channel_samples = resize_samples_u8p; break;
  215.     case AV_SAMPLE_FMT_S16P: s->delay_channel = delay_channel_s16p;
  216.                              s->resize_channel_samples = resize_samples_s16p; break;
  217.     case AV_SAMPLE_FMT_S32P: s->delay_channel = delay_channel_s32p;
  218.                              s->resize_channel_samples = resize_samples_s32p; break;
  219.     case AV_SAMPLE_FMT_FLTP: s->delay_channel = delay_channel_fltp;
  220.                              s->resize_channel_samples = resize_samples_fltp; break;
  221.     case AV_SAMPLE_FMT_DBLP: s->delay_channel = delay_channel_dblp;
  222.                              s->resize_channel_samples = resize_samples_dblp; break;
  223.     }
  224.  
  225.     return 0;
  226. }
  227.  
  228. static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
  229.                            char *res, int res_len, int flags)
  230. {
  231.     int ret = AVERROR(ENOSYS);
  232.     AVFilterLink *inlink = ctx->inputs[0];
  233.     AudioDelayContext *s = ctx->priv;
  234.  
  235.     if (!strcmp(cmd, "delays")) {
  236. //        if(flags & AVFILTER_CMD_FLAG_ONE) {
  237. //            return 0;
  238. //        }
  239.         int64_t delay;
  240.         av_sscanf(args, "%"SCNd64, &delay);
  241.         if (delay > SIZE_MAX) {
  242.             av_log(ctx, AV_LOG_ERROR, "Requested delay is too big.\n");
  243.             return AVERROR(EINVAL);
  244.         }
  245.  
  246.         s->max_delay = 0;
  247.         delay = delay * inlink->sample_rate / 1000.0;
  248.         for (int i = 0; i < s->nb_delays; i++) {
  249.             ChanDelay *d = &s->chandelay[i];
  250.             av_log(ctx, AV_LOG_INFO, "old delay: %ld\n", d->delay);
  251.             ret = s->resize_channel_samples(d, delay);
  252.             s->max_delay = FFMAX(s->max_delay, d->delay);
  253.             av_log(ctx, AV_LOG_INFO, "new delay: %ld\n", d->delay);
  254.         }
  255.     }
  256.  
  257.     return ret;
  258. }
  259.  
  260. static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
  261. {
  262.     AVFilterContext *ctx = inlink->dst;
  263.     AVFilterLink *outlink = ctx->outputs[0];
  264.     AudioDelayContext *s = ctx->priv;
  265.     AVFrame *out_frame;
  266.     int i;
  267.  
  268.     if (ctx->is_disabled || !s->delays)
  269.         return ff_filter_frame(outlink, frame);
  270.  
  271.     out_frame = ff_get_audio_buffer(outlink, frame->nb_samples);
  272.     if (!out_frame) {
  273.         av_frame_free(&frame);
  274.         return AVERROR(ENOMEM);
  275.     }
  276.     av_frame_copy_props(out_frame, frame);
  277.  
  278.     for (i = 0; i < s->nb_delays; i++) {
  279.         ChanDelay *d = &s->chandelay[i];
  280.         const uint8_t *src = frame->extended_data[i];
  281.         uint8_t *dst = out_frame->extended_data[i];
  282.  
  283.         if (!d->delay)
  284.             memcpy(dst, src, frame->nb_samples * s->block_align);
  285.         else
  286.             s->delay_channel(d, frame->nb_samples, src, dst);
  287.     }
  288.  
  289.     out_frame->pts = s->next_pts;
  290.     s->next_pts += av_rescale_q(frame->nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base);
  291.     av_frame_free(&frame);
  292.     return ff_filter_frame(outlink, out_frame);
  293. }
  294.  
  295. static int activate(AVFilterContext *ctx)
  296. {
  297.     AVFilterLink *inlink = ctx->inputs[0];
  298.     AVFilterLink *outlink = ctx->outputs[0];
  299.     AudioDelayContext *s = ctx->priv;
  300.     AVFrame *frame = NULL;
  301.     int ret, status;
  302.     int64_t pts;
  303.  
  304.     FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
  305.  
  306.     if (s->padding) {
  307.         int nb_samples = FFMIN(s->padding, 2048);
  308.  
  309.         frame = ff_get_audio_buffer(outlink, nb_samples);
  310.         if (!frame)
  311.             return AVERROR(ENOMEM);
  312.         s->padding -= nb_samples;
  313.  
  314.         av_samples_set_silence(frame->extended_data, 0,
  315.                                frame->nb_samples,
  316.                                outlink->channels,
  317.                                frame->format);
  318.  
  319.         frame->pts = s->next_pts;
  320.         if (s->next_pts != AV_NOPTS_VALUE)
  321.             s->next_pts += av_rescale_q(nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base);
  322.  
  323.         return ff_filter_frame(outlink, frame);
  324.     }
  325.  
  326.     ret = ff_inlink_consume_frame(inlink, &frame);
  327.     if (ret < 0)
  328.         return ret;
  329.  
  330.     if (ret > 0)
  331.         return filter_frame(inlink, frame);
  332.  
  333.     if (ff_inlink_acknowledge_status(inlink, &status, &pts)) {
  334.         if (status == AVERROR_EOF)
  335.             s->eof = 1;
  336.     }
  337.  
  338.     if (s->eof && s->max_delay) {
  339.         int nb_samples = FFMIN(s->max_delay, 2048);
  340.  
  341.         frame = ff_get_audio_buffer(outlink, nb_samples);
  342.         if (!frame)
  343.             return AVERROR(ENOMEM);
  344.         s->max_delay -= nb_samples;
  345.  
  346.         av_samples_set_silence(frame->extended_data, 0,
  347.                                frame->nb_samples,
  348.                                outlink->channels,
  349.                                frame->format);
  350.  
  351.         frame->pts = s->next_pts;
  352.         return filter_frame(inlink, frame);
  353.     }
  354.  
  355.     if (s->eof && s->max_delay == 0) {
  356.         ff_outlink_set_status(outlink, AVERROR_EOF, s->next_pts);
  357.         return 0;
  358.     }
  359.  
  360.     if (!s->eof)
  361.         FF_FILTER_FORWARD_WANTED(outlink, inlink);
  362.  
  363.     return FFERROR_NOT_READY;
  364. }
  365.  
  366. static av_cold void uninit(AVFilterContext *ctx)
  367. {
  368.     AudioDelayContext *s = ctx->priv;
  369.  
  370.     if (s->chandelay) {
  371.         for (int i = 0; i < s->nb_delays; i++)
  372.             av_freep(&s->chandelay[i].samples);
  373.     }
  374.     av_freep(&s->chandelay);
  375. }
  376.  
  377. static const AVFilterPad adelay_inputs[] = {
  378.     {
  379.         .name         = "default",
  380.         .type         = AVMEDIA_TYPE_AUDIO,
  381.         .config_props = config_input,
  382.     },
  383. };
  384.  
  385. static const AVFilterPad adelay_outputs[] = {
  386.     {
  387.         .name = "default",
  388.         .type = AVMEDIA_TYPE_AUDIO,
  389.     },
  390. };
  391.  
  392. const AVFilter ff_af_adelay = {
  393.     .name          = "adelay",
  394.     .description   = NULL_IF_CONFIG_SMALL("Delay one or more audio channels."),
  395.     .priv_size     = sizeof(AudioDelayContext),
  396.     .priv_class    = &adelay_class,
  397.     .activate      = activate,
  398.     .uninit        = uninit,
  399.     FILTER_INPUTS(adelay_inputs),
  400.     FILTER_OUTPUTS(adelay_outputs),
  401.     FILTER_SAMPLEFMTS(AV_SAMPLE_FMT_U8P, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P,
  402.                       AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBLP),
  403.     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
  404.     .process_command = process_command,
  405. };
  406.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement