[FFmpeg-devel] [PATCH] avfilter/avf_showcqt: add option for lower resolution

Muhammad Faiz mfcc64 at gmail.com
Wed Jun 11 12:05:18 CEST 2014


motivation: lower cpu usage
resolution can be 1920x1080 or 960x540
thanks
-------------- next part --------------
diff --git a/doc/filters.texi b/doc/filters.texi
index d8ed7f7..7803d2d 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -10222,7 +10222,7 @@ settb=AVTB
 @end itemize
 
 @section showcqt
-Convert input audio to a video output (at full HD resolution), representing
+Convert input audio to a video output representing
 frequency spectrum logarithmically (using constant Q transform with
 Brown-Puckette algorithm), with musical tone scale, from E0 to D#10 (10 octaves).
 
@@ -10250,6 +10250,10 @@ Specify gamma. Lower gamma makes the spectrum more contrast, higher gamma
 makes the spectrum having more range. Acceptable value is [1.0, 7.0].
 Default value is @code{3.0}.
 
+ at item fullhd
+If set to 1 (the default), the video size is 1920x1080 (full HD),
+if set to 0, the video size is 960x540. Use this option to make CPU usage lower.
+
 @item fps
 Specify video fps. Default value is @code{25}.
 
@@ -10276,6 +10280,12 @@ ffplay -f lavfi 'amovie=a.mp3, asplit [a][out1]; [a] showcqt=fps=30:count=5 [out
 @end example
 
 @item
+Playing at 960x540 and lower CPU usage:
+ at example
+ffplay -f lavfi 'amovie=a.mp3, asplit [a][out1]; [a] showcqt=fullhd=0:count=3 [out0]'
+ at end example
+
+ at item
 A1 and its harmonics: A1, A2, (near)E3, A3:
 @example
 ffplay -f lavfi 'aevalsrc=0.1*sin(2*PI*55*t)+0.1*sin(4*PI*55*t)+0.1*sin(6*PI*55*t)+0.1*sin(8*PI*55*t),
diff --git a/libavfilter/avf_showcqt.c b/libavfilter/avf_showcqt.c
index 0870507..de87397 100644
--- a/libavfilter/avf_showcqt.c
+++ b/libavfilter/avf_showcqt.c
@@ -66,9 +66,9 @@ typedef struct {
     FFTComplex *fft_result_right;
     SparseCoeff *coeff_sort;
     SparseCoeff *coeffs[VIDEO_WIDTH];
+    uint8_t *spectogram;
     int coeffs_len[VIDEO_WIDTH];
     uint8_t font_color[VIDEO_WIDTH];
-    uint8_t spectogram[SPECTOGRAM_HEIGHT][VIDEO_WIDTH][3];
     int64_t frame_count;
     int spectogram_count;
     int spectogram_index;
@@ -79,6 +79,7 @@ typedef struct {
     double timeclamp;   /* lower timeclamp, time-accurate, higher timeclamp, freq-accurate (at low freq)*/
     float coeffclamp;   /* lower coeffclamp, more precise, higher coeffclamp, faster */
     float gamma;        /* lower gamma, more contrast, higher gamma, more range */
+    int fullhd;         /* if true, output video is at full HD resolution, otherwise it will be halved */
     int fps;            /* the required fps is so strict, so it's enough to be int, but 24000/1001 etc cannot be encoded */
     int count;          /* fps * count = transform rate */
 } ShowCQTContext;
@@ -91,6 +92,7 @@ static const AVOption showcqt_options[] = {
     { "timeclamp", "set timeclamp", OFFSET(timeclamp), AV_OPT_TYPE_DOUBLE, { .dbl = 0.17 }, 0.1, 1.0, FLAGS },
     { "coeffclamp", "set coeffclamp", OFFSET(coeffclamp), AV_OPT_TYPE_FLOAT, { .dbl = 1 }, 0.1, 10, FLAGS },
     { "gamma", "set gamma", OFFSET(gamma), AV_OPT_TYPE_FLOAT, { .dbl = 3 }, 1, 7, FLAGS },
+    { "fullhd", "set full HD resolution", OFFSET(fullhd), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, FLAGS },
     { "fps", "set video fps", OFFSET(fps), AV_OPT_TYPE_INT, { .i64 = 25 }, 10, 100, FLAGS },
     { "count", "set number of transform per frame", OFFSET(count), AV_OPT_TYPE_INT, { .i64 = 6 }, 1, 30, FLAGS },
     { NULL }
@@ -110,6 +112,7 @@ static av_cold void uninit(AVFilterContext *ctx)
     av_freep(&s->fft_result_left);
     av_freep(&s->fft_result_right);
     av_freep(&s->coeff_sort);
+    av_freep(&s->spectogram);
     av_frame_free(&s->outpicref);
 }
 
@@ -159,6 +162,10 @@ static int config_output(AVFilterLink *outlink)
     int rate = inlink->sample_rate;
     double max_len = rate * (double) s->timeclamp;
     int64_t start_time, end_time;
+    int video_scale = s->fullhd ? 2 : 1;
+    int video_width = (VIDEO_WIDTH/2) * video_scale;
+    int video_height = (VIDEO_HEIGHT/2) * video_scale;
+    int spectogram_height = (SPECTOGRAM_HEIGHT/2) * video_scale;
     s->fft_bits = ceil(log2(max_len));
     fft_len = 1 << s->fft_bits;
 
@@ -178,11 +185,11 @@ static int config_output(AVFilterLink *outlink)
         return AVERROR(ENOMEM);
 
     /* initializing font */
-    for (x = 0; x < VIDEO_WIDTH; x++)
+    for (x = 0; x < video_width; x++)
     {
-        if (x >= (12*3+8)*16 && x < (12*4+8)*16)
+        if (x >= (12*3+8)*8*video_scale && x < (12*4+8)*8*video_scale)
         {
-            float fx = (x-(12*3+8)*16) * (1.0f/192.0f);
+            float fx = (x-(12*3+8)*8*video_scale) * (2.0f/(192.0f*video_scale));
             float sv = sinf(M_PI*fx);
             s->font_color[x] = sv*sv*255.0f + 0.5f;
         }
@@ -280,21 +287,25 @@ static int config_output(AVFilterLink *outlink)
     end_time = av_gettime_relative();
     av_log(ctx, AV_LOG_INFO, "Elapsed time %.6f s (fft_len=%u, num_coeffs=%u)\n", 1e-6 * (end_time-start_time), fft_len, num_coeffs);
 
-    outlink->w = VIDEO_WIDTH;
-    outlink->h = VIDEO_HEIGHT;
+    outlink->w = video_width;
+    outlink->h = video_height;
 
     s->req_fullfilled = 0;
     s->spectogram_index = 0;
     s->frame_count = 0;
     s->spectogram_count = 0;
     s->remaining_fill = fft_len >> 1;
-    memset(s->spectogram, 0, VIDEO_WIDTH * SPECTOGRAM_HEIGHT * 3);
     memset(s->fft_data, 0, fft_len * sizeof(*s->fft_data));
 
     s->outpicref = ff_get_video_buffer(outlink, outlink->w, outlink->h);
     if (!s->outpicref)
         return AVERROR(ENOMEM);
 
+    s->spectogram = av_malloc(spectogram_height * s->outpicref->linesize[0]);
+    if (!s->spectogram)
+        return AVERROR(ENOMEM);
+    memset(s->spectogram, 0, spectogram_height * s->outpicref->linesize[0]);
+
     outlink->sample_aspect_ratio = av_make_q(1, 1);
     outlink->time_base = av_make_q(1, s->fps);
     outlink->frame_rate = av_make_q(s->fps, 1);
@@ -309,6 +320,12 @@ static int plot_cqt(AVFilterLink *inlink)
     int fft_len = 1 << s->fft_bits;
     FFTSample result[VIDEO_WIDTH][4];
     int x, y, ret = 0;
+    int linesize = s->outpicref->linesize[0];
+    int video_scale = s->fullhd ? 2 : 1;
+    int video_width = (VIDEO_WIDTH/2) * video_scale;
+    int spectogram_height = (SPECTOGRAM_HEIGHT/2) * video_scale;
+    int spectogram_start = (SPECTOGRAM_START/2) * video_scale;
+    int font_height = (FONT_HEIGHT/2) * video_scale;
 
     /* real part contains left samples, imaginary part contains right samples */
     memcpy(s->fft_result_left, s->fft_data, fft_len * sizeof(*s->fft_data));
@@ -362,29 +379,37 @@ static int plot_cqt(AVFilterLink *inlink)
         result[x][2] = 255.0f * powf(FFMIN(1.0f,result[x][2]), g);
     }
 
-    for (x = 0; x < VIDEO_WIDTH; x++)
+    if (!s->fullhd)
+        for (x = 0; x < video_width; x++)
+        {
+            result[x][0] = 0.5f * (result[2*x][0] + result[2*x+1][0]);
+            result[x][1] = 0.5f * (result[2*x][1] + result[2*x+1][1]);
+            result[x][2] = 0.5f * (result[2*x][2] + result[2*x+1][2]);
+            result[x][3] = 0.5f * (result[2*x][3] + result[2*x+1][3]);
+        }
+
+    for (x = 0; x < video_width; x++)
     {
-        s->spectogram[s->spectogram_index][x][0] = result[x][0] + 0.5f;
-        s->spectogram[s->spectogram_index][x][1] = result[x][1] + 0.5f;
-        s->spectogram[s->spectogram_index][x][2] = result[x][2] + 0.5f;
+        s->spectogram[s->spectogram_index*linesize + 3*x] = result[x][0] + 0.5f;
+        s->spectogram[s->spectogram_index*linesize + 3*x + 1] = result[x][1] + 0.5f;
+        s->spectogram[s->spectogram_index*linesize + 3*x + 2] = result[x][2] + 0.5f;
     }
 
     /* drawing */
     if (!s->spectogram_count)
     {
         uint8_t *data = (uint8_t*) s->outpicref->data[0];
-        int linesize = s->outpicref->linesize[0];
         float rcp_result[VIDEO_WIDTH];
 
-        for (x = 0; x < VIDEO_WIDTH; x++)
+        for (x = 0; x < video_width; x++)
             rcp_result[x] = 1.0f / (result[x][3]+0.0001f);
 
         /* drawing bar */
-        for (y = 0; y < SPECTOGRAM_HEIGHT; y++)
+        for (y = 0; y < spectogram_height; y++)
         {
-            float height = (SPECTOGRAM_HEIGHT - y) * (1.0f/SPECTOGRAM_HEIGHT);
+            float height = (spectogram_height - y) * (1.0f/spectogram_height);
             uint8_t *lineptr = data + y * linesize;
-            for (x = 0; x < VIDEO_WIDTH; x++)
+            for (x = 0; x < video_width; x++)
             {
                 float mul;
                 if (result[x][3] <= height)
@@ -401,62 +426,60 @@ static int plot_cqt(AVFilterLink *inlink)
                     *lineptr++ = mul * result[x][2] + 0.5f;
                 }
             }
-
         }
 
         /* drawing font */
-        for (y = 0; y < FONT_HEIGHT; y++)
+        for (y = 0; y < font_height; y++)
         {
-            uint8_t *lineptr = data + (SPECTOGRAM_HEIGHT + y) * linesize;
-            memcpy(lineptr, s->spectogram[s->spectogram_index], VIDEO_WIDTH*3);
+            uint8_t *lineptr = data + (spectogram_height + y) * linesize;
+            memcpy(lineptr, s->spectogram + s->spectogram_index * linesize, video_width*3);
         }
-        for (x = 0; x < VIDEO_WIDTH; x += VIDEO_WIDTH/10)
+        for (x = 0; x < video_width; x += video_width/10)
         {
             int u;
             static const char str[] = "EF G A BC D ";
-            uint8_t *startptr = data + SPECTOGRAM_HEIGHT * linesize + x * 3;
+            uint8_t *startptr = data + spectogram_height * linesize + x * 3;
             for (u = 0; str[u]; u++)
             {
                 int v;
                 for (v = 0; v < 16; v++)
                 {
-                    uint8_t *p = startptr + 2 * v * linesize + 16 * 3 * u;
-                    int ux = x + 16 * u;
+                    uint8_t *p = startptr + v * linesize * video_scale + 8 * 3 * u * video_scale;
+                    int ux = x + 8 * u * video_scale;
                     int mask;
                     for (mask = 0x80; mask; mask >>= 1)
                     {
                         if (mask & avpriv_vga16_font[str[u] * 16 + v])
                         {
-                            p[0] = p[linesize] = 255 - s->font_color[ux];
-                            p[1] = p[linesize+1] = 0;
-                            p[2] = p[linesize+2] = s->font_color[ux];
-                            p[3] = p[linesize+3] = 255 - s->font_color[ux+1];
-                            p[4] = p[linesize+4] = 0;
-                            p[5] = p[linesize+5] = s->font_color[ux+1];
+                            p[0] = 255 - s->font_color[ux];
+                            p[1] = 0;
+                            p[2] = s->font_color[ux];
+                            if (video_scale == 2)
+                            {
+                                p[linesize] = p[0];
+                                p[linesize+1] = p[1];
+                                p[linesize+2] = p[2];
+                                p[3] = p[linesize+3] = 255 - s->font_color[ux+1];
+                                p[4] = p[linesize+4] = 0;
+                                p[5] = p[linesize+5] = s->font_color[ux+1];
+                            }
                         }
-                        p += 6;
-                        ux += 2;
+                        p += 3 * video_scale;
+                        ux += video_scale;
                     }
                 }
             }
-
         }
 
         /* drawing spectogram/sonogram */
-        if (linesize == VIDEO_WIDTH * 3)
         {
-            int total_length = VIDEO_WIDTH * SPECTOGRAM_HEIGHT * 3;
-            int back_length = VIDEO_WIDTH * s->spectogram_index * 3;
-            data += SPECTOGRAM_START * VIDEO_WIDTH * 3;
-            memcpy(data, s->spectogram[s->spectogram_index], total_length - back_length);
+            int total_length = linesize * spectogram_height;
+            int back_length = linesize * s->spectogram_index;
+            data += spectogram_start * linesize;
+            memcpy(data, s->spectogram + s->spectogram_index*linesize, total_length - back_length);
             data += total_length - back_length;
             if(back_length)
-                memcpy(data, s->spectogram[0], back_length);
-        }
-        else
-        {
-            for (y = 0; y < SPECTOGRAM_HEIGHT; y++)
-                memcpy(data + (SPECTOGRAM_START + y) * linesize, s->spectogram[(s->spectogram_index + y) % SPECTOGRAM_HEIGHT], VIDEO_WIDTH * 3);
+                memcpy(data, s->spectogram, back_length);
         }
 
         s->outpicref->pts = s->frame_count;
@@ -465,7 +488,7 @@ static int plot_cqt(AVFilterLink *inlink)
         s->frame_count++;
     }
     s->spectogram_count = (s->spectogram_count + 1) % s->count;
-    s->spectogram_index = (s->spectogram_index + SPECTOGRAM_HEIGHT - 1) % SPECTOGRAM_HEIGHT;
+    s->spectogram_index = (s->spectogram_index + spectogram_height - 1) % spectogram_height;
     return ret;
 }
 


More information about the ffmpeg-devel mailing list