From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.ffmpeg.org (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTPS id C0C484B439 for ; Mon, 21 Jul 2025 12:05:16 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTP id 8656368C466; Mon, 21 Jul 2025 15:05:08 +0300 (EEST) Received: from mail-pf1-f174.google.com (mail-pf1-f174.google.com [209.85.210.174]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTPS id 0CFB268C41B for ; Mon, 21 Jul 2025 15:05:02 +0300 (EEST) Received: by mail-pf1-f174.google.com with SMTP id d2e1a72fcca58-748d982e97cso3702487b3a.1 for ; Mon, 21 Jul 2025 05:05:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1753099500; x=1753704300; darn=ffmpeg.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=9lKSL3FqZKVbaCS7AmHJc26l0XNdlDq4o3Tg27OT8Fw=; b=NjtfJSdOIjtojRVzmsmxgBZrfmOaunOto6Uk13mXEvQzbwKddTAI3E/u9bb8umfqU4 MjxHuoPFVGTOcvuhUF7/yLMrUX4Je3EVwWaZT2d7Q7Lud74CCUvdZOlsfRs7sxCLbQX6 dOjJdVh/knJw1lqAJFhMm4LY6iD5kUMEMYdCWIRHLaOn2pSe9IYBskhthWr3rgzEBAhG ixaG+ObeN41XLuBj4e1xNbTPwI31oBrjX8X4VjqVRZ5ZGyILkM4GEzUvQgZv5Yr9A8DL 6vi/VrVhjz68MyUqV/Dm2OVT35flqW0i4aAx3gS4iFxSkuhB5l9PBHBNU0YOVu6+SBs6 e5pA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1753099500; x=1753704300; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=9lKSL3FqZKVbaCS7AmHJc26l0XNdlDq4o3Tg27OT8Fw=; b=m2hVeum6r4EI4aTML9ymIampyk6nQRNGdVbtlxHizAzBKGxOiHaBwtKnH413htTp/+ 3G1JuVWe+7EnTVNBYnSTbBEIs4esc3WQH3QuABdUtpSbo4rj/nhYPZW3uxJDtrcWbyb0 xWaDhO+EIOzL/rWqzLDkI/wTYLy3oA+iJT8ExXWvWbhLSF3OhbtQhW7PAWFuvhE7neHO GlV1N5p3DjzrQagyrIn4z6mFu+YouJNO/hU7Qz9gpufduU2Y5x/JDLvCzCYwXDaK5kSy CMFD861aFxjBPfXrP4enWfqgpOmjhPjBZDzTcZNeAKLO3QLmnm2a9BpWG4lBcGq7CGcQ MFHA== X-Gm-Message-State: AOJu0Yyjl2+2DPfmtp36lR/JoC5S5yefd950ffH3c8upphXu/1o9pp3X RtLek7P1SHfQJfS9M3rByWsRerxylZnEZafPj3HiMXWrmrEzGiQCP4zKM3mmHg== X-Gm-Gg: ASbGnctXaQsN1UPeih3INS3C+mTUOF5ipa4CmNVb1Tjj3KfNJ3k9QM1iKPE6PlEnAPj tRCDaRJYppExiUXwDvovybey0LMOoV4c5zOTy9eOWdeY9V3VsqxKw3BuCnXa34O+x2oo4HPfNWD eVclEBwWFSPexkqKjYndpay/6QugYzi6cUPnIDOIvW1+sbaoHuMJYR5tRdXd1y9TxxUNh+Lx8Mx GVLtBKobrbkqPe+9/rzmka841tTPm4wC0CvkXZorAHLB6fnlFYwG8t2wNnKsWdgCjjAARS70Ejv pvBIzxuwPrbSg9DH/sNZpL+xA40ivELX/xDr9zc9AE23J+739DXQzKhMbMk1U8vRaAZeEn9OjQX JWskb1b2hYmDyuGIVdjnSdNpRJgJ9EdY= X-Google-Smtp-Source: AGHT+IFl3RBCLkAd9BHZYQhSFcsLJPKzsweKA8QPv/5IUmRmDhl8nZ3jvwHGP1p5JfVvlgOdpstNTQ== X-Received: by 2002:a05:6a00:a8a:b0:748:e1e4:71d9 with SMTP id d2e1a72fcca58-75724e7a7f9mr23331250b3a.22.1753099499777; Mon, 21 Jul 2025 05:04:59 -0700 (PDT) Received: from cen.mioffice.cn ([43.224.245.228]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-759cb974219sm5520809b3a.116.2025.07.21.05.04.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Jul 2025 05:04:59 -0700 (PDT) From: cenzhanquan2@gmail.com To: ffmpeg-devel@ffmpeg.org Date: Mon, 21 Jul 2025 20:04:42 +0800 Message-Id: <20250721120444.2125750-2-cenzhanquan2@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250721120444.2125750-1-cenzhanquan2@gmail.com> References: <20250721112752.2105845-1-cenzhanquan2@gmail.com> <20250721120444.2125750-1-cenzhanquan2@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v2 1/3] avfilter/volume: add volume scaling utilities. X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: zhanquan cen , your_email@domain.com Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Archived-At: List-Archive: List-Post: From: zhanquan cen --- volume.c | 168 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ volume.h | 44 +++++++++++++++ 2 files changed, 212 insertions(+) create mode 100644 volume.c create mode 100644 volume.h diff --git a/volume.c b/volume.c new file mode 100644 index 0000000000..373895924c --- /dev/null +++ b/volume.c @@ -0,0 +1,168 @@ + +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +/** + * @file + * audio volume for src filter + */ +#include "libavutil/mem.h" +#include "volume.h" +static inline void fade_samples_s16_small(int16_t *dst, const int16_t *src, + int nb_samples, int chs, int16_t dst_volume, int16_t src_volume) +{ + int i, j, k = 0; + int32_t step; + step = ((dst_volume - src_volume) << 15) / nb_samples; + for (i = 0; i < nb_samples; i++) { + for (j = 0; j < chs; j++, k++) { + dst[k] = av_clip_int16((src[k] * (src_volume + (step * i >> 15)) + 0x4000) >> 15); + } + } +} +static inline void scale_samples_u8(uint8_t *dst, const uint8_t *src, + int nb_samples, int volume) +{ + int i; + for (i = 0; i < nb_samples; i++) + dst[i] = av_clip_uint8(((((int64_t)src[i] - 128) * volume + 128) >> 8) + 128); +} +static inline void scale_samples_u8_small(uint8_t *dst, const uint8_t *src, + int nb_samples, int volume) +{ + int i; + for (i = 0; i < nb_samples; i++) + dst[i] = av_clip_uint8((((src[i] - 128) * volume + 128) >> 8) + 128); +} +static inline void scale_samples_s16(uint8_t *dst, const uint8_t *src, + int nb_samples, int volume) +{ + int i; + int16_t *smp_dst = (int16_t *)dst; + const int16_t *smp_src = (const int16_t *)src; + for (i = 0; i < nb_samples; i++) + smp_dst[i] = av_clip_int16(((int64_t)smp_src[i] * volume + 128) >> 8); +} +static inline void scale_samples_s16_small(uint8_t *dst, const uint8_t *src, + int nb_samples, int volume) +{ + int i; + int16_t *smp_dst = (int16_t *)dst; + const int16_t *smp_src = (const int16_t *)src; + for (i = 0; i < nb_samples; i++) + smp_dst[i] = av_clip_int16((smp_src[i] * volume + 128) >> 8); +} +static inline void scale_samples_s32(uint8_t *dst, const uint8_t *src, + int nb_samples, int volume) +{ + int i; + int32_t *smp_dst = (int32_t *)dst; + const int32_t *smp_src = (const int32_t *)src; + for (i = 0; i < nb_samples; i++) + smp_dst[i] = av_clipl_int32((((int64_t)smp_src[i] * volume + 128) >> 8)); +} +static av_cold void scaler_init(VolumeContext *vol) +{ + int32_t volume_i = (int32_t)(vol->volume * 256 + 0.5); + vol->samples_align = 1; + switch (av_get_packed_sample_fmt(vol->sample_fmt)) { + case AV_SAMPLE_FMT_U8: + if (volume_i < 0x1000000) + vol->scale_samples = scale_samples_u8_small; + else + vol->scale_samples = scale_samples_u8; + break; + case AV_SAMPLE_FMT_S16: + if (volume_i < 0x10000) + vol->scale_samples = scale_samples_s16_small; + else + vol->scale_samples = scale_samples_s16; + break; + case AV_SAMPLE_FMT_S32: + vol->scale_samples = scale_samples_s32; + break; + case AV_SAMPLE_FMT_FLT: + vol->samples_align = 4; + break; + case AV_SAMPLE_FMT_DBL: + vol->samples_align = 8; + break; + } +} +int volume_set(VolumeContext *vol, double volume) +{ + vol->volume = volume; + vol->volume_last = -1.0f; + scaler_init(vol); + return 0; +} +void volume_scale(VolumeContext *vol, AVFrame *frame) +{ + int planar, planes, plane_size, p; + planar = av_sample_fmt_is_planar(frame->format); + planes = planar ? frame->ch_layout.nb_channels : 1; + plane_size = frame->nb_samples * (planar ? 1 : frame->ch_layout.nb_channels); + if (frame->format == AV_SAMPLE_FMT_S16 || + frame->format == AV_SAMPLE_FMT_S16P) { + int32_t vol_isrc = (int32_t)(vol->volume_last * 256 + 0.5); + int32_t volume_i = (int32_t)(vol->volume * 256 + 0.5); + if (volume_i != vol_isrc) { + for (p = 0; p < planes; p++) { + vol->fade_samples(frame->extended_data[p], + frame->extended_data[p], + frame->nb_samples, planar ? 1 : frame->ch_layout.nb_channels, + volume_i, vol_isrc); + } + } else { + for (p = 0; p < planes; p++) { + vol->scale_samples(frame->extended_data[p], + frame->extended_data[p], + plane_size, volume_i); + } + } + vol->volume_last = vol->volume; + } else if (frame->format == AV_SAMPLE_FMT_FLT || + frame->format == AV_SAMPLE_FMT_FLTP) { + for (p = 0; p < planes; p++) { + vol->fdsp->vector_fmul_scalar((float *)frame->extended_data[p], + (float *)frame->extended_data[p], + vol->volume, plane_size); + } + } else { + for (p = 0; p < planes; p++) { + vol->fdsp->vector_dmul_scalar((double *)frame->extended_data[p], + (double *)frame->extended_data[p], + vol->volume, plane_size); + } + } +} +int volume_init(VolumeContext *vol, enum AVSampleFormat sample_fmt) +{ + vol->sample_fmt = sample_fmt; + vol->volume_last = -1.0f; + vol->volume = 1.0f; + vol->fdsp = avpriv_float_dsp_alloc(0); + if (!vol->fdsp) + return AVERROR(ENOMEM); + scaler_init(vol); + vol->fade_samples = fade_samples_s16_small; + return 0; +} +void volume_uninit(VolumeContext *vol) +{ + av_freep(&vol->fdsp); +} diff --git a/volume.h b/volume.h new file mode 100644 index 0000000000..141e839e90 --- /dev/null +++ b/volume.h @@ -0,0 +1,44 @@ + +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +/** + * @file + * audio volume for src filter + */ +#ifndef LIBAVFILTER_VOLUME_H +#define LIBAVFILTER_VOLUME_H +#include +#include "libavutil/samplefmt.h" +#include "libavutil/float_dsp.h" +#include "libavutil/frame.h" +typedef struct VolumeContext { + AVFloatDSPContext *fdsp; + enum AVSampleFormat sample_fmt; + int samples_align; + double volume_last; + double volume; + void (*scale_samples)(uint8_t *dst, const uint8_t *src, int nb_samples, + int volume); + void (*fade_samples)(int16_t *dst, const int16_t *src, + int nb_samples, int chs, int16_t dst_volume, int16_t src_volume); +} VolumeContext; +int volume_init(VolumeContext *vol, enum AVSampleFormat sample_fmt); +void volume_scale(VolumeContext *vol, AVFrame *frame); +int volume_set(VolumeContext *vol, double volume); +void volume_uninit(VolumeContext *vol); +#endif /* LIBAVFILTER_VOLUME_H */ -- 2.34.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".