Browse code

avfilter/vf_waveform: add text to graticule

Signed-off-by: Paul B Mahol <onemda@gmail.com>

Paul B Mahol authored on 2016/03/06 17:46:34
Showing 2 changed files
... ...
@@ -13175,6 +13175,14 @@ Display green graticule showing legal broadcast ranges.
13175 13175
 
13176 13176
 @item opacity, o
13177 13177
 Set graticule opacity.
13178
+
13179
+@item flags, fl
13180
+Set graticule flags.
13181
+
13182
+@table @samp
13183
+@item numbers
13184
+Draw numbers above lines. By default enabled.
13185
+@end table
13178 13186
 @end table
13179 13187
 
13180 13188
 @section xbr
... ...
@@ -23,6 +23,7 @@
23 23
 #include "libavutil/opt.h"
24 24
 #include "libavutil/parseutils.h"
25 25
 #include "libavutil/pixdesc.h"
26
+#include "libavutil/xga_font_data.h"
26 27
 #include "avfilter.h"
27 28
 #include "formats.h"
28 29
 #include "internal.h"
... ...
@@ -57,6 +58,7 @@ typedef struct WaveformContext {
57 57
     int            *emin[4][4];
58 58
     int            *peak;
59 59
     int            filter;
60
+    int            flags;
60 61
     int            bits;
61 62
     int            max;
62 63
     int            size;
... ...
@@ -104,6 +106,9 @@ static const AVOption waveform_options[] = {
104 104
         { "green", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "graticule" },
105 105
     { "opacity", "set graticule opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS },
106 106
     { "o",       "set graticule opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS },
107
+    { "flags", "set graticule flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=1}, 0, 1, FLAGS, "flags" },
108
+    { "fl",    "set graticule flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=1}, 0, 1, FLAGS, "flags" },
109
+        { "numbers",  "draw numbers", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "flags" },
107 110
     { NULL }
108 111
 };
109 112
 
... ...
@@ -1236,6 +1241,108 @@ static void blend_hline16(uint16_t *dst, int width, float o1, float o2, int v)
1236 1236
     }
1237 1237
 }
1238 1238
 
1239
+static void draw_htext(AVFrame *out, int x, int y, float o1, float o2, const char *txt, const uint8_t color[4])
1240
+{
1241
+    const uint8_t *font;
1242
+    int font_height;
1243
+    int i, plane;
1244
+
1245
+    font = avpriv_cga_font,   font_height =  8;
1246
+
1247
+    for (plane = 0; plane < 4 && out->data[plane]; plane++) {
1248
+        for (i = 0; txt[i]; i++) {
1249
+            int char_y, mask;
1250
+            int v = color[plane];
1251
+
1252
+            uint8_t *p = out->data[plane] + y * out->linesize[plane] + (x + i * 8);
1253
+            for (char_y = 0; char_y < font_height; char_y++) {
1254
+                for (mask = 0x80; mask; mask >>= 1) {
1255
+                    if (font[txt[i] * font_height + char_y] & mask)
1256
+                        p[0] = p[0] * o2 + v * o1;
1257
+                    p++;
1258
+                }
1259
+                p += out->linesize[plane] - 8;
1260
+            }
1261
+        }
1262
+    }
1263
+}
1264
+
1265
+static void draw_htext16(AVFrame *out, int x, int y, int mult, float o1, float o2, const char *txt, const uint8_t color[4])
1266
+{
1267
+    const uint8_t *font;
1268
+    int font_height;
1269
+    int i, plane;
1270
+
1271
+    font = avpriv_cga_font,   font_height =  8;
1272
+
1273
+    for (plane = 0; plane < 4 && out->data[plane]; plane++) {
1274
+        for (i = 0; txt[i]; i++) {
1275
+            int char_y, mask;
1276
+            int v = color[plane] * mult;
1277
+
1278
+            uint16_t *p = (uint16_t *)(out->data[plane] + y * out->linesize[plane]) + (x + i * 8);
1279
+            for (char_y = 0; char_y < font_height; char_y++) {
1280
+                for (mask = 0x80; mask; mask >>= 1) {
1281
+                    if (font[txt[i] * font_height + char_y] & mask)
1282
+                        p[0] = p[0] * o2 + v * o1;
1283
+                    p++;
1284
+                }
1285
+                p += out->linesize[plane] / 2 - 8;
1286
+            }
1287
+        }
1288
+    }
1289
+}
1290
+
1291
+static void draw_vtext(AVFrame *out, int x, int y, float o1, float o2, const char *txt, const uint8_t color[4])
1292
+{
1293
+    const uint8_t *font;
1294
+    int font_height;
1295
+    int i, plane;
1296
+
1297
+    font = avpriv_cga_font,   font_height =  8;
1298
+
1299
+    for (plane = 0; plane < 4 && out->data[plane]; plane++) {
1300
+        for (i = 0; txt[i]; i++) {
1301
+            int char_y, mask;
1302
+            int v = color[plane];
1303
+
1304
+            for (char_y = font_height - 1; char_y >= 0; char_y--) {
1305
+                uint8_t *p = out->data[plane] + (y + i * 10) * out->linesize[plane] + x;
1306
+                for (mask = 0x80; mask; mask >>= 1) {
1307
+                    if (font[txt[i] * font_height + font_height - 1 - char_y] & mask)
1308
+                        p[char_y] = p[char_y] * o2 + v * o1;
1309
+                    p += out->linesize[plane];
1310
+                }
1311
+            }
1312
+        }
1313
+    }
1314
+}
1315
+
1316
+static void draw_vtext16(AVFrame *out, int x, int y, int mult, float o1, float o2, const char *txt, const uint8_t color[4])
1317
+{
1318
+    const uint8_t *font;
1319
+    int font_height;
1320
+    int i, plane;
1321
+
1322
+    font = avpriv_cga_font,   font_height =  8;
1323
+
1324
+    for (plane = 0; plane < 4 && out->data[plane]; plane++) {
1325
+        for (i = 0; txt[i]; i++) {
1326
+            int char_y, mask;
1327
+            int v = color[plane] * mult;
1328
+
1329
+            for (char_y = 0; char_y < font_height; char_y++) {
1330
+                uint16_t *p = (uint16_t *)(out->data[plane] + (y + i * 10) * out->linesize[plane]) + x;
1331
+                for (mask = 0x80; mask; mask >>= 1) {
1332
+                    if (font[txt[i] * font_height + font_height - 1 - char_y] & mask)
1333
+                        p[char_y] = p[char_y] * o2 + v * o1;
1334
+                    p += out->linesize[plane] / 2;
1335
+                }
1336
+            }
1337
+        }
1338
+    }
1339
+}
1340
+
1239 1341
 static void graticule_none(WaveformContext *s, AVFrame *out)
1240 1342
 {
1241 1343
 }
... ...
@@ -1244,12 +1351,13 @@ static void graticule_green_row(WaveformContext *s, AVFrame *out)
1244 1244
 {
1245 1245
     const float o1 = s->opacity;
1246 1246
     const float o2 = 1. - o1;
1247
-    int c, p, l, offset = 0;
1247
+    int k = 0, c, p, l, offset = 0;
1248 1248
 
1249 1249
     for (c = 0; c < s->ncomp; c++) {
1250
-        if (!((1 << c) & s->pcomp))
1250
+        if (!((1 << c) & s->pcomp) || (!s->display && k > 0))
1251 1251
             continue;
1252 1252
 
1253
+        k++;
1253 1254
         for (p = 0; p < s->ncomp; p++) {
1254 1255
             const int v = green_yuva_color[p];
1255 1256
             for (l = 0; l < FF_ARRAY_ELEMS(lines[0]); l++) {
... ...
@@ -1260,6 +1368,14 @@ static void graticule_green_row(WaveformContext *s, AVFrame *out)
1260 1260
             }
1261 1261
         }
1262 1262
 
1263
+        for (l = 0; l < FF_ARRAY_ELEMS(lines[0]) && (s->flags & 1); l++) {
1264
+            const int x = offset + (s->mirror ? 255 - lines[c][l] : lines[c][l]) - 10;
1265
+            char text[16];
1266
+
1267
+            snprintf(text, sizeof(text), "%d", lines[c][l]);
1268
+            draw_vtext(out, x, 2, o1, o2, text, green_yuva_color);
1269
+        }
1270
+
1263 1271
         offset += 256 * s->display;
1264 1272
     }
1265 1273
 }
... ...
@@ -1269,22 +1385,31 @@ static void graticule16_green_row(WaveformContext *s, AVFrame *out)
1269 1269
     const float o1 = s->opacity;
1270 1270
     const float o2 = 1. - o1;
1271 1271
     const int mult = s->size / 256;
1272
-    int c, p, l, offset = 0;
1272
+    int k = 0, c, p, l, offset = 0;
1273 1273
 
1274 1274
     for (c = 0; c < s->ncomp; c++) {
1275
-        if (!((1 << c) & s->pcomp))
1275
+        if (!((1 << c) & s->pcomp) || (!s->display && k > 0))
1276 1276
             continue;
1277 1277
 
1278
+        k++;
1278 1279
         for (p = 0; p < s->ncomp; p++) {
1279 1280
             const int v = green_yuva_color[p] * mult;
1280 1281
             for (l = 0; l < FF_ARRAY_ELEMS(lines[0]); l++) {
1281
-                int x = offset + (s->mirror ? 255 - lines[c][l] : lines[c][l]) * mult;
1282
+                int x = offset + (s->mirror ? s->size - 1 - lines[c][l] * mult : lines[c][l] * mult);
1282 1283
                 uint16_t *dst = (uint16_t *)(out->data[p]) + x;
1283 1284
 
1284 1285
                 blend_vline16(dst, out->height, out->linesize[p], o1, o2, v);
1285 1286
             }
1286 1287
         }
1287 1288
 
1289
+        for (l = 0; l < FF_ARRAY_ELEMS(lines[0]) && (s->flags & 1); l++) {
1290
+            const int x = offset + (s->mirror ? s->size - 1 - lines[c][l] * mult : lines[c][l] * mult) - 10;
1291
+            char text[16];
1292
+
1293
+            snprintf(text, sizeof(text), "%d", lines[c][l] * mult);
1294
+            draw_vtext16(out, x, 2, mult, o1, o2, text, green_yuva_color);
1295
+        }
1296
+
1288 1297
         offset += s->size * s->display;
1289 1298
     }
1290 1299
 }
... ...
@@ -1293,12 +1418,13 @@ static void graticule_green_column(WaveformContext *s, AVFrame *out)
1293 1293
 {
1294 1294
     const float o1 = s->opacity;
1295 1295
     const float o2 = 1. - o1;
1296
-    int c, p, l, offset = 0;
1296
+    int k = 0, c, p, l, offset = 0;
1297 1297
 
1298 1298
     for (c = 0; c < s->ncomp; c++) {
1299
-        if (!((1 << c) & s->pcomp))
1299
+        if ((!((1 << c) & s->pcomp) || (!s->display && k > 0)))
1300 1300
             continue;
1301 1301
 
1302
+        k++;
1302 1303
         for (p = 0; p < s->ncomp; p++) {
1303 1304
             const int v = green_yuva_color[p];
1304 1305
             for (l = 0; l < FF_ARRAY_ELEMS(lines[0]); l++) {
... ...
@@ -1309,6 +1435,15 @@ static void graticule_green_column(WaveformContext *s, AVFrame *out)
1309 1309
             }
1310 1310
         }
1311 1311
 
1312
+        for (l = 0; l < FF_ARRAY_ELEMS(lines[0]) && (s->flags & 1); l++) {
1313
+            const int y = offset + (s->mirror ? 255 - lines[c][l] : lines[c][l]) - 10;
1314
+            char text[16];
1315
+
1316
+            snprintf(text, sizeof(text), "%d", lines[c][l]);
1317
+            draw_htext(out, 2, y,
1318
+                       o1, o2, text, green_yuva_color);
1319
+        }
1320
+
1312 1321
         offset += 256 * s->display;
1313 1322
     }
1314 1323
 }
... ...
@@ -1318,22 +1453,32 @@ static void graticule16_green_column(WaveformContext *s, AVFrame *out)
1318 1318
     const float o1 = s->opacity;
1319 1319
     const float o2 = 1. - o1;
1320 1320
     const int mult = s->size / 256;
1321
-    int c, p, l, offset = 0;
1321
+    int k = 0, c, p, l, offset = 0;
1322 1322
 
1323 1323
     for (c = 0; c < s->ncomp; c++) {
1324
-        if (!((1 << c) & s->pcomp))
1324
+        if ((!((1 << c) & s->pcomp) || (!s->display && k > 0)))
1325 1325
             continue;
1326 1326
 
1327
+        k++;
1327 1328
         for (p = 0; p < s->ncomp; p++) {
1328 1329
             const int v = green_yuva_color[p] * mult;
1329 1330
             for (l = 0; l < FF_ARRAY_ELEMS(lines[0]); l++) {
1330
-                int y = offset + (s->mirror ? 255 - lines[c][l] : lines[c][l]) * mult;
1331
+                int y = offset + (s->mirror ? s->size - 1 - lines[c][l] * mult : lines[c][l] * mult);
1331 1332
                 uint16_t *dst = (uint16_t *)(out->data[p] + y * out->linesize[p]);
1332 1333
 
1333 1334
                 blend_hline16(dst, out->width, o1, o2, v);
1334 1335
             }
1335 1336
         }
1336 1337
 
1338
+        for (l = 0; l < FF_ARRAY_ELEMS(lines[0]) && (s->flags & 1); l++) {
1339
+            const int y = offset + (s->mirror ? s->size - 1 - lines[c][l] * mult : lines[c][l] * mult) - 10;
1340
+            char text[16];
1341
+
1342
+            snprintf(text, sizeof(text), "%d", lines[c][l] * mult);
1343
+            draw_htext16(out, 2, y,
1344
+                         mult, o1, o2, text, green_yuva_color);
1345
+        }
1346
+
1337 1347
         offset += s->size * s->display;
1338 1348
     }
1339 1349
 }