Unified · Split
| @@ -93,6 +93,11 @@ typedef struct DynamicAudioNormalizerContext { · 92 unmodified lines | ||
| 93 | 93 | AVFrame *window; |
| 94 | 94 | } DynamicAudioNormalizerContext; |
| 95 | 95 | |
| 96 | +typedef struct ThreadData { | |
| 97 | + AVFrame *in, *out; | |
| 98 | + int enabled; | |
| 99 | +} ThreadData; | |
| 100 | + | |
| 96 | 101 | #define OFFSET(x) offsetof(DynamicAudioNormalizerContext, x) |
| 97 | 102 | #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM |
| 98 | 103 | |
| @@ -521,6 +526,20 @@ static void update_gain_history(DynamicAudioNormalizerContext *s, int channel, · 422 unmodified lines | ||
| 521 | 526 | } |
| 522 | 527 | } |
| 523 | 528 | |
| 529 | +static int update_gain_histories(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) | |
| 530 | +{ | |
| 531 | + DynamicAudioNormalizerContext *s = ctx->priv; | |
| 532 | + AVFrame *analyze_frame = arg; | |
| 533 | + const int channels = s->channels; | |
| 534 | + const int start = (channels * jobnr) / nb_jobs; | |
| 535 | + const int end = (channels * (jobnr+1)) / nb_jobs; | |
| 536 | + | |
| 537 | + for (int c = start; c < end; c++) | |
| 538 | + update_gain_history(s, c, get_max_local_gain(s, analyze_frame, c)); | |
| 539 | + | |
| 540 | + return 0; | |
| 541 | +} | |
| 542 | + | |
| 524 | 543 | static inline double update_value(double new, double old, double aggressiveness) |
| 525 | 544 | { |
| 526 | 545 | av_assert0((aggressiveness >= 0.0) && (aggressiveness <= 1.0)); |
| @@ -655,8 +674,9 @@ static void perform_compression(DynamicAudioNormalizerContext *s, AVFrame *frame · 128 unmodified lines | ||
| 655 | 674 | } |
| 656 | 675 | } |
| 657 | 676 | |
| 658 | −static int analyze_frame(DynamicAudioNormalizerContext *s, AVFilterLink *outlink, AVFrame **frame) | |
| 677 | +static int analyze_frame(AVFilterContext *ctx, AVFilterLink *outlink, AVFrame **frame) | |
| 659 | 678 | { |
| 679 | + DynamicAudioNormalizerContext *s = ctx->priv; | |
| 660 | 680 | AVFrame *analyze_frame; |
| 661 | 681 | |
| 662 | 682 | if (s->dc_correction || s->compress_factor > DBL_EPSILON) { |
| @@ -716,34 +736,49 @@ static int analyze_frame(DynamicAudioNormalizerContext *s, AVFilterLink *outlink · 53 unmodified lines | ||
| 716 | 736 | for (int c = 0; c < s->channels; c++) |
| 717 | 737 | update_gain_history(s, c, gain); |
| 718 | 738 | } else { |
| 719 | − for (int c = 0; c < s->channels; c++) | |
| 720 | − update_gain_history(s, c, get_max_local_gain(s, analyze_frame, c)); | |
| 739 | + ff_filter_execute(ctx, update_gain_histories, analyze_frame, NULL, | |
| 740 | + FFMIN(s->channels, ff_filter_get_nb_threads(ctx))); | |
| 721 | 741 | } |
| 722 | 742 | |
| 723 | 743 | return 0; |
| 724 | 744 | } |
| 725 | 745 | |
| 726 | −static void amplify_frame(DynamicAudioNormalizerContext *s, AVFrame *in, | |
| 727 | − AVFrame *frame, int enabled) | |
| 746 | +static void amplify_channel(DynamicAudioNormalizerContext *s, AVFrame *in, | |
| 747 | + AVFrame *frame, int enabled, int c) | |
| 728 | 748 | { |
| 729 | − for (int c = 0; c < s->channels; c++) { | |
| 730 | − const int bypass = bypass_channel(s, frame, c); | |
| 731 | − const double *src_ptr = (const double *)in->extended_data[c]; | |
| 732 | − double *dst_ptr = (double *)frame->extended_data[c]; | |
| 733 | − double current_amplification_factor; | |
| 734 | − | |
| 735 | − cqueue_dequeue(s->gain_history_smoothed[c], ¤t_amplification_factor); | |
| 749 | + const int bypass = bypass_channel(s, frame, c); | |
| 750 | + const double *src_ptr = (const double *)in->extended_data[c]; | |
| 751 | + double *dst_ptr = (double *)frame->extended_data[c]; | |
| 752 | + double current_amplification_factor; | |
| 736 | 753 | |
| 737 | − for (int i = 0; i < frame->nb_samples && enabled && !bypass; i++) { | |
| 738 | − const double amplification_factor = fade(s->prev_amplification_factor[c], | |
| 739 | − current_amplification_factor, i, | |
| 740 | − frame->nb_samples); | |
| 754 | + cqueue_dequeue(s->gain_history_smoothed[c], ¤t_amplification_factor); | |
| 741 | 755 | |
| 742 | − dst_ptr[i] = src_ptr[i] * amplification_factor; | |
| 743 | − } | |
| 756 | + for (int i = 0; i < frame->nb_samples && enabled && !bypass; i++) { | |
| 757 | + const double amplification_factor = fade(s->prev_amplification_factor[c], | |
| 758 | + current_amplification_factor, i, | |
| 759 | + frame->nb_samples); | |
| 744 | 760 | |
| 745 | − s->prev_amplification_factor[c] = current_amplification_factor; | |
| 761 | + dst_ptr[i] = src_ptr[i] * amplification_factor; | |
| 746 | 762 | } |
| 763 | + | |
| 764 | + s->prev_amplification_factor[c] = current_amplification_factor; | |
| 765 | +} | |
| 766 | + | |
| 767 | +static int amplify_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) | |
| 768 | +{ | |
| 769 | + DynamicAudioNormalizerContext *s = ctx->priv; | |
| 770 | + ThreadData *td = arg; | |
| 771 | + AVFrame *out = td->out; | |
| 772 | + AVFrame *in = td->in; | |
| 773 | + const int enabled = td->enabled; | |
| 774 | + const int channels = s->channels; | |
| 775 | + const int start = (channels * jobnr) / nb_jobs; | |
| 776 | + const int end = (channels * (jobnr+1)) / nb_jobs; | |
| 777 | + | |
| 778 | + for (int ch = start; ch < end; ch++) | |
| 779 | + amplify_channel(s, in, out, enabled, ch); | |
| 780 | + | |
| 781 | + return 0; | |
| 747 | 782 | } |
| 748 | 783 | |
| 749 | 784 | static int filter_frame(AVFilterLink *inlink, AVFrame *in) |
| @@ -751,6 +786,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) · 1 unmodified line | ||
| 751 | 786 | AVFilterContext *ctx = inlink->dst; |
| 752 | 787 | DynamicAudioNormalizerContext *s = ctx->priv; |
| 753 | 788 | AVFilterLink *outlink = ctx->outputs[0]; |
| 789 | + ThreadData td; | |
| 754 | 790 | int ret; |
| 755 | 791 | |
| 756 | 792 | while (((s->queue.available >= s->filter_size) || |
| @@ -773,7 +809,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) · 16 unmodified lines | ||
| 773 | 809 | av_frame_copy_props(out, in); |
| 774 | 810 | } |
| 775 | 811 | |
| 776 | − amplify_frame(s, in, out, is_enabled > 0.); | |
| 812 | + td.in = in; | |
| 813 | + td.out = out; | |
| 814 | + td.enabled = is_enabled > 0.; | |
| 815 | + ff_filter_execute(ctx, amplify_channels, &td, NULL, | |
| 816 | + FFMIN(s->channels, ff_filter_get_nb_threads(ctx))); | |
| 817 | + | |
| 777 | 818 | s->pts = out->pts + av_rescale_q(out->nb_samples, av_make_q(1, outlink->sample_rate), |
| 778 | 819 | outlink->time_base); |
| 779 | 820 | if (out != in) |
| @@ -783,7 +824,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) · 3 unmodified lines | ||
| 783 | 824 | return ret; |
| 784 | 825 | } |
| 785 | 826 | |
| 786 | − ret = analyze_frame(s, outlink, &in); | |
| 827 | + ret = analyze_frame(ctx, outlink, &in); | |
| 787 | 828 | if (ret < 0) |
| 788 | 829 | return ret; |
| 789 | 830 | if (!s->eof) { |
| @@ -940,6 +981,7 @@ const AVFilter ff_af_dynaudnorm = { · 150 unmodified lines | ||
| 940 | 981 | FILTER_OUTPUTS(avfilter_af_dynaudnorm_outputs), |
| 941 | 982 | FILTER_SINGLE_SAMPLEFMT(AV_SAMPLE_FMT_DBLP), |
| 942 | 983 | .priv_class = &dynaudnorm_class, |
| 943 | − .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, | |
| 984 | + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | | |
| 985 | + AVFILTER_FLAG_SLICE_THREADS, | |
| 944 | 986 | .process_command = process_command, |
| 945 | 987 | }; |