From patchwork Wed Nov 2 19:40:26 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pallavi Kumari X-Patchwork-Id: 1261 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.90.1 with SMTP id o1csp438716vsb; Wed, 2 Nov 2016 12:46:23 -0700 (PDT) X-Received: by 10.194.96.164 with SMTP id dt4mr4342049wjb.28.1478115983281; Wed, 02 Nov 2016 12:46:23 -0700 (PDT) Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id t14si39681283wme.97.2016.11.02.12.46.22; Wed, 02 Nov 2016 12:46:23 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id B445E689AA6; Wed, 2 Nov 2016 21:46:16 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-yw0-f180.google.com (mail-yw0-f180.google.com [209.85.161.180]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 2C40A689259 for ; Wed, 2 Nov 2016 21:46:10 +0200 (EET) Received: by mail-yw0-f180.google.com with SMTP id l124so21821118ywb.3 for ; Wed, 02 Nov 2016 12:46:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=RLicK6AKmcKvQakRyJPN5tBfMdKqyrrjxWJMRARZ9oA=; b=AqiuPthXLR8HQTalq6Uz1bbePYUi2Pc85Qmlzg11E8I5yOpzY4LGWsWf2dtGq1mUKg GHdTjqX4nAwOynPtnC098zLREUcS4XXP8/A0e9jS7aGV2Nru0ObKu3RM9II4TX90lZrX EC0G94ZT55oQlTzcgruA/Gko+Hp9GNEEfcc6aOdiWZOnPYLN/i7jzXNqTb6RNYZkCq+U v22DpFw2wdSTRCbweypxC2KSep1teJl2rkz2s1qf9k4eY+qXqlF2jkOGacMmcyog7b3y QWuPDA56wCY2JAIYCAFLPfA4pDyzivA5cK4A22wqcAK1o5ogsIuJ+I3Xrpoy5edhe/zB FgrQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=RLicK6AKmcKvQakRyJPN5tBfMdKqyrrjxWJMRARZ9oA=; b=KBDHxZhPA8mQxM4ED/6k52vKwsGLyBVIToY8HlR5Lq1qMXnwHpOjjEkYNbrTLphFt+ lA8FUEr2oRpyOkMDI2Dd6f18o6iBJ7HNic/CVskGQj1W21ewtghg62erslQIoJvMjTZG EVvwycS6PFWDmFKqPbMpP7tjPyG7XwRrK2IWvdzkaaFpzY5rroBHdaU3dPBt+05YO08U 26RKRSHWIiM3bL3v74Xr1hCA28ujAgcsjqbINZCSxN/vqznf4X4pM7b8YwVt7cUrg9Di wNDkQtbYGQjM+EgIATtSV4jG+53t9VpNBFm/rFPeOlwypIvQa36pMYuzfarN9loNZIBw 73nw== X-Gm-Message-State: ABUngvfXsHh9ijw5U4tEMyE+l/NtYQ94g5g1ujj/T3hDv73yzaht+I1OJsfdPfD9/P4O6AYR9GeRzuBOty1h3Q== X-Received: by 10.36.99.76 with SMTP id j73mr3667178itc.49.1478115627677; Wed, 02 Nov 2016 12:40:27 -0700 (PDT) MIME-Version: 1.0 Received: by 10.107.18.88 with HTTP; Wed, 2 Nov 2016 12:40:26 -0700 (PDT) In-Reply-To: <20161102004445.GP4602@nb4> References: <20161015001558.GN4602@nb4> <20161026123111.GZ4602@nb4> <20161026215428.GN4602@nb4> <20161027230824.GU4602@nb4> <20161102004445.GP4602@nb4> From: Pallavi Kumari Date: Thu, 3 Nov 2016 01:10:26 +0530 Message-ID: To: Michael Niedermayer X-Content-Filtered-By: Mailman/MimeDel 2.1.20 Subject: Re: [FFmpeg-devel] [OPW] OPW Project Proposal X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 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: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Necessary changes has been done. PFA. Usage: ./ffmpeg -i kpg.mp3 -filter_complex peakpoints=wsize=16 -f null - On Wed, Nov 2, 2016 at 6:14 AM, Michael Niedermayer wrote: > On Wed, Nov 02, 2016 at 05:00:09AM +0530, Pallavi Kumari wrote: > > Hi Michael, > > > > I have attached a working patch with the mail. PFA. > > > > Usage: > > > > > ./ffmpeg -i kpg.mp3 -filter_complex peakpoints=input=kpg.mp3:wsize=16 > > I realize now, theres a mistake in this, you must provide a output > as in > ./ffmpeg -i kpg.mp3 -af peakpoints -f null - > > without some output like "-f null -" it wont read the file fully and > wont pass it through filter_frame() > > you could see this failure as in: > ./ffmpeg -i ~/videos/matrixbench_mpeg2.mpg -af volumedetect -f null - > vs. > ./ffmpeg -i ~/videos/matrixbench_mpeg2.mpg -af volumedetect > > you get the histogram from the volume detect filter in the first case > but not the 2nd. > > [...] > -- > Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB > > Many things microsoft did are stupid, but not doing something just because > microsoft did it is even more stupid. If everything ms did were stupid they > would be bankrupt already. > From e10f73d363d0313774bcb132b3b1f2417fcfba11 Mon Sep 17 00:00:00 2001 From: Atana Date: Thu, 3 Nov 2016 01:05:51 +0530 Subject: [PATCH] avfilter: added peakpoints filter --- libavfilter/af_peakpoints.c | 226 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100644 libavfilter/af_peakpoints.c diff --git a/libavfilter/af_peakpoints.c b/libavfilter/af_peakpoints.c new file mode 100644 index 0000000..9265c47 --- /dev/null +++ b/libavfilter/af_peakpoints.c @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2016 Atana + * + * 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 + */ + +#include "libavcodec/avcodec.h" +#include "libavcodec/avfft.h" +#include "libavformat/avformat.h" +#include "libswscale/swscale.h" +#include "avfilter.h" +#include "audio.h" +#include "libavutil/opt.h" + + +/* Structure to contain peak points context */ +typedef struct { + const AVClass *class; + double *data; + int nsamples; + int index; + double *peaks; + int size; // number of peaks + int windowSize; + //char *inputFile; +} PeakPointsContext; + +/* returns maximum value from an array conditioned on start and end index */ +static double getMax(double *res_arr, int startIndex, int endIndex) { + int i; + double max = res_arr[startIndex]; + for (i = startIndex; i <= endIndex; i++) { + if (res_arr[i] > max) { + max = res_arr[i]; + } + } + return max; +} + +/* Stores peak frequency for each window(of chunkSize) in peaks array */ +static void getPeakPointInChunk(int chunkSize, double *res_arr, int size, double *peaks) { + int i = 0, peakIndex = 0; + int startIndex = 0; + double max; + // get a chunk and find max value in it + while (i < size) { + if (i % chunkSize-1 == 0) { + max = getMax(res_arr, startIndex, i); + peaks[peakIndex++] = max; + startIndex = startIndex + chunkSize; + } + i += 1; + } +} + +/* Get peaks points from windowed frequency domain data*/ +static int getPeakPoints(PeakPointsContext *ppc) { + int i, m, k, size, chunkSize, pSize, chunkSampleSize, resSize; + double *fft_res; + void *avc; + RDFTContext *rdftC; + FFTSample *data; + + size = ppc->index; + m = log2(ppc->windowSize); + chunkSize = ppc->windowSize; + chunkSampleSize = size/chunkSize; + resSize = chunkSize * chunkSampleSize; + + fft_res = av_malloc(sizeof(double) * resSize); + + if (!fft_res) { + av_log(avc, AV_LOG_ERROR, "Cann't allocate memmory for storing fft data\n"); + return 0; + } + + + rdftC = av_rdft_init(m, DFT_R2C); + data = av_malloc(sizeof(FFTSample)*chunkSize); + + if (!data) { + av_log(avc, AV_LOG_ERROR, "Cann't allocate memmory for chunk fft data\n"); + return 0; + } + // FFT transform for windowed time domain data + // window is of size chunkSize + k = 0; + while (k < resSize) { + //copy data + for (i = 0; i < chunkSize; i++) { + data[i] = ppc->data[i+k]; + } + //calculate FFT + av_rdft_calc(rdftC, data); + for (i = 0; i < chunkSize; i++) { + fft_res[i+k] = data[i]; + } + k = k + chunkSize; + } + + av_rdft_end(rdftC); + pSize = resSize/chunkSize; + ppc->size = pSize; + ppc->peaks = av_malloc(sizeof(double)*pSize); + + if (!ppc->peaks) { + av_log(avc, AV_LOG_ERROR, "Cann't allocate memory for peak storage\n"); + return 0; + } + + getPeakPointInChunk(chunkSize, fft_res, resSize, ppc->peaks); + return 1; +} + + +#define OFFSET(x) offsetof(PeakPointsContext, x) + +static const AVOption peakpoints_options[] = { + { "wsize", "set window size", OFFSET(windowSize), AV_OPT_TYPE_INT, {.i64=16}, 0, INT_MAX}, + { NULL }, +}; + +AVFILTER_DEFINE_CLASS(peakpoints); + +static av_cold int init(AVFilterContext *ctx) +{ + PeakPointsContext *p = ctx->priv; + + if (p->windowSize < 16) { + av_log(ctx, AV_LOG_ERROR, "window size must be greater than or equal to 16\n"); + return AVERROR(EINVAL); + } + + p->index = 0; + p->size = 0; + p->data = av_malloc(sizeof(double)*10000); + + if (!p->data) { + av_log(ctx, AV_LOG_ERROR, "Cann't allocate memmory for audio data\n"); + return AVERROR(EINVAL); + } + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *samples) +{ + AVFilterContext *ctx = inlink->dst; + PeakPointsContext *p = ctx->priv; + + // store audio data + p->data[p->index] = (double)*samples->data[0]; + p->index = p->index + 1; + + return ff_filter_frame(inlink->dst->outputs[0], samples); +} + +static void ppointsStats(AVFilterContext *ctx, PeakPointsContext *p) { + int i, ret; + ret = getPeakPoints(p); + + if (ret && p->size) { + // print peaks + av_log(ctx, AV_LOG_INFO, "######## Peak points are ########\n"); + for (i = 0; i < p->size; i++) { + av_log(ctx, AV_LOG_INFO, "%f\n", p->peaks[i]); + } + } else if (p->size || !ret) { + av_log(ctx, AV_LOG_ERROR, "Peak points not retrieved\n"); + return; + } +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + PeakPointsContext *p = ctx->priv; + + ppointsStats(ctx, p); + + // free allocated memories + av_freep(&p->data); + av_freep(&p->peaks); +} + +static const AVFilterPad peakpoints_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad peakpoints_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + }, + { NULL } +}; + +AVFilter ff_af_peakpoints = { + .name = "peakpoints", + .description = NULL_IF_CONFIG_SMALL("peak points from frequency domain windowed data."), + .init = init, + .uninit = uninit, + //.query_formats = query_formats, + .priv_size = sizeof(PeakPointsContext), + .inputs = peakpoints_inputs, + .outputs = peakpoints_outputs, + .priv_class = &peakpoints_class, +}; -- 1.9.1