Browse code

avfilter/vf_histogram: improve waveform speed

Signed-off-by: Marton Balint <cus@passwd.hu>

Marton Balint authored on 2013/10/02 04:53:57
Showing 1 changed files
... ...
@@ -48,6 +48,7 @@ typedef struct HistogramContext {
48 48
     int            waveform_mode;
49 49
     int            display_mode;
50 50
     int            levels_mode;
51
+    const AVPixFmtDescriptor *desc;
51 52
 } HistogramContext;
52 53
 
53 54
 #define OFFSET(x) offsetof(HistogramContext, x)
... ...
@@ -117,9 +118,9 @@ static const uint8_t white_gbrp_color[4] = { 255, 255, 255, 255 };
117 117
 static int config_input(AVFilterLink *inlink)
118 118
 {
119 119
     HistogramContext *h = inlink->dst->priv;
120
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
121 120
 
122
-    h->ncomp = desc->nb_components;
121
+    h->desc  = av_pix_fmt_desc_get(inlink->format);
122
+    h->ncomp = h->desc->nb_components;
123 123
 
124 124
     switch (inlink->format) {
125 125
     case AV_PIX_FMT_GBRAP:
... ...
@@ -164,6 +165,41 @@ static int config_output(AVFilterLink *outlink)
164 164
     return 0;
165 165
 }
166 166
 
167
+static void gen_waveform(HistogramContext *h, AVFrame *inpicref, AVFrame *outpicref,
168
+                         int component, int intensity, int offset, int col_mode)
169
+{
170
+    const int plane = h->desc->comp[component].plane;
171
+    const int src_linesize = inpicref->linesize[plane];
172
+    const int dst_linesize = outpicref->linesize[plane];
173
+    uint8_t *src_data = inpicref->data[plane];
174
+    uint8_t *dst_data = outpicref->data[plane] + (col_mode ? offset * dst_linesize : offset);
175
+    uint8_t * const dst_line = dst_data;
176
+    const uint8_t max = 255 - intensity;
177
+    const int src_h = inpicref->height;
178
+    const int src_w = inpicref->width;
179
+    uint8_t *dst, *p;
180
+    int y;
181
+
182
+    for (y = 0; y < src_h; y++) {
183
+        const uint8_t *src_data_end = src_data + src_w;
184
+        dst = dst_line;
185
+        for (p = src_data; p < src_data_end; p++) {
186
+            uint8_t *target;
187
+            if (col_mode)
188
+                target = dst++ + dst_linesize * *p;
189
+            else
190
+                target = dst_data + *p;
191
+            if (*target <= max)
192
+                *target += intensity;
193
+            else
194
+                *target = 255;
195
+        }
196
+        src_data += src_linesize;
197
+        dst_data += dst_linesize;
198
+    }
199
+}
200
+
201
+
167 202
 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
168 203
 {
169 204
     HistogramContext *h   = inlink->dst->priv;
... ...
@@ -227,34 +263,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
227 227
         }
228 228
         break;
229 229
     case MODE_WAVEFORM:
230
-        if (h->waveform_mode) {
231
-            for (k = 0; k < h->ncomp; k++) {
232
-                int offset = k * 256 * h->display_mode;
233
-                for (i = 0; i < inlink->w; i++) {
234
-                    for (j = 0; j < inlink->h; j++) {
235
-                        int pos = (offset +
236
-                                   in->data[k][j * in->linesize[k] + i]) *
237
-                                  out->linesize[k] + i;
238
-                        unsigned value = out->data[k][pos];
239
-                        value = FFMIN(value + h->step, 255);
240
-                        out->data[k][pos] = value;
241
-                    }
242
-                }
243
-            }
244
-        } else {
245
-            for (k = 0; k < h->ncomp; k++) {
246
-                int offset = k * 256 * h->display_mode;
247
-                for (i = 0; i < inlink->h; i++) {
248
-                    src = in ->data[k] + i * in ->linesize[k];
249
-                    dst = out->data[k] + i * out->linesize[k];
250
-                    for (j = 0; j < inlink->w; j++) {
251
-                        int pos = src[j] + offset;
252
-                        unsigned value = dst[pos];
253
-                        value = FFMIN(value + h->step, 255);
254
-                        dst[pos] = value;
255
-                    }
256
-                }
257
-            }
230
+        for (k = 0; k < h->ncomp; k++) {
231
+            int offset = k * 256 * h->display_mode;
232
+            gen_waveform(h, in, out, k, h->step, offset, h->waveform_mode);
258 233
         }
259 234
         break;
260 235
     case MODE_COLOR: