FFmpeg
Loading...
Searching...
No Matches
qrencode.c
Go to the documentation of this file.
1/*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19/**
20 * @file QR encoder source and filter.
21 *
22 * A QR code (quick-response code) is a type of two-dimensional matrix
23 * barcode, invented in 1994, by Japanese company Denso Wave for
24 * labelling automobile parts.
25 *
26 * This source uses the libqrencode library to generate QR code:
27 * https://fukuchi.org/works/qrencode/
28 */
29
30//#define DEBUG
31
32#include "config_components.h"
33
34#include "libavutil/internal.h"
35#include "libavutil/imgutils.h"
36#include "libavutil/mem.h"
37#include "libavutil/opt.h"
38#include "libavutil/lfg.h"
40
41#include "avfilter.h"
42#include "drawutils.h"
43#include "filters.h"
44#include "formats.h"
45#include "textutils.h"
46#include "video.h"
47#include "libswscale/swscale.h"
48
49#include <qrencode.h>
50
68
69static const char *const var_names[] = {
70 "dar",
71 "duration",
72 "hsub", "vsub",
73 "main_h", "H", ///< height of the input video
74 "main_w", "W", ///< width of the input video
75 "n", ///< number of frame
76 "pict_type",
77 "qr_w", "w", ///< width of the QR code
78 "rendered_padded_qr_w", "Q", ///< width of the rendered QR code
79 "rendered_qr_w", "q", ///< width of the rendered QR code
80 "sar",
81 "t", ///< timestamp expressed in seconds
82 "x",
83 "y",
84 NULL
85};
86
87#define V(name_) qr->var_values[VAR_##name_]
88
93
94typedef struct QREncodeContext {
95 const AVClass *class;
96
98 char *x_expr;
99 char *y_expr;
101
105
108
109 unsigned char *text;
110 char *textfile;
111 uint64_t pts;
112
113 int level;
115
118
120 FFDrawColor draw_foreground_color; ///< foreground color
121 FFDrawColor draw_background_color; ///< background color
122
123 /* these are only used when nothing must be encoded */
125 FFDrawColor draw0_background_color; ///< background color
126
127 uint8_t *qrcode_data[4];
129 uint8_t *qrcode_mask_data[4];
131
132 /* only used for filter to contain scaled image to blend on top of input */
135
138
140
141 int expansion; ///< expansion mode to use for the text
142 FFExpandTextContext expand_text; ///< expand text in case expansion is enabled
143 AVBPrint expanded_text; ///< used to contain the expanded text
144
146 AVLFG lfg; ///< random generator
149
150#define OFFSET(x) offsetof(QREncodeContext, x)
151#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
152#define TFLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
153
154#define COMMON_OPTIONS \
155 { "qrcode_width", "set rendered QR code width expression", OFFSET(rendered_qrcode_width_expr), AV_OPT_TYPE_STRING, {.str = "64"}, 0, INT_MAX, FLAGS }, \
156 { "q", "set rendered QR code width expression", OFFSET(rendered_qrcode_width_expr), AV_OPT_TYPE_STRING, {.str = "64"}, 0, INT_MAX, FLAGS }, \
157 { "padded_qrcode_width", "set rendered padded QR code width expression", OFFSET(rendered_padded_qrcode_width_expr), AV_OPT_TYPE_STRING, {.str = "q"}, 0, INT_MAX, FLAGS }, \
158 { "Q", "set rendered padded QR code width expression", OFFSET(rendered_padded_qrcode_width_expr), AV_OPT_TYPE_STRING, {.str = "q"}, 0, INT_MAX, FLAGS }, \
159 { "case_sensitive", "generate code which is case sensitive", OFFSET(case_sensitive), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS }, \
160 { "cs", "generate code which is case sensitive", OFFSET(case_sensitive), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS }, \
161 \
162 { "level", "error correction level, lowest is L", OFFSET(level), AV_OPT_TYPE_INT, { .i64 = AVCOL_SPC_UNSPECIFIED }, 0, QR_ECLEVEL_H, .flags = FLAGS, .unit = "level"}, \
163 { "l", "error correction level, lowest is L", OFFSET(level), AV_OPT_TYPE_INT, { .i64 = AVCOL_SPC_UNSPECIFIED }, 0, QR_ECLEVEL_H, .flags = FLAGS, .unit = "level"}, \
164 { "L", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = QR_ECLEVEL_L }, 0, 0, FLAGS, .unit = "level" }, \
165 { "M", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = QR_ECLEVEL_M }, 0, 0, FLAGS, .unit = "level" }, \
166 { "Q", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = QR_ECLEVEL_Q }, 0, 0, FLAGS, .unit = "level" }, \
167 { "H", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = QR_ECLEVEL_H }, 0, 0, FLAGS, .unit = "level" }, \
168 \
169 {"expansion", "set the expansion mode", OFFSET(expansion), AV_OPT_TYPE_INT, {.i64=EXPANSION_NORMAL}, 0, 2, FLAGS, .unit = "expansion"}, \
170 {"none", "set no expansion", OFFSET(expansion), AV_OPT_TYPE_CONST, {.i64 = EXPANSION_NONE}, 0, 0, FLAGS, .unit = "expansion"}, \
171 {"normal", "set normal expansion", OFFSET(expansion), AV_OPT_TYPE_CONST, {.i64 = EXPANSION_NORMAL}, 0, 0, FLAGS, .unit = "expansion"}, \
172 \
173 { "foreground_color", "set QR foreground color", OFFSET(foreground_color), AV_OPT_TYPE_COLOR, {.str = "black"}, 0, 0, FLAGS }, \
174 { "fc", "set QR foreground color", OFFSET(foreground_color), AV_OPT_TYPE_COLOR, {.str = "black"}, 0, 0, FLAGS }, \
175 { "background_color", "set QR background color", OFFSET(background_color), AV_OPT_TYPE_COLOR, {.str = "white"}, 0, 0, FLAGS }, \
176 { "bc", "set QR background color", OFFSET(background_color), AV_OPT_TYPE_COLOR, {.str = "white"}, 0, 0, FLAGS }, \
177 \
178 {"text", "set text to encode", OFFSET(text), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS}, \
179 {"textfile", "set text file to encode", OFFSET(textfile), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS}, \
180
181static const char *const fun2_names[] = {
182 "rand"
183};
184
185static double drand(void *opaque, double min, double max)
186{
187 return min + (max-min) / UINT_MAX * av_lfg_get(opaque);
188}
189
190static const ff_eval_func2 fun2[] = {
191 drand,
192 NULL
193};
194
195static int func_pts(void *ctx, AVBPrint *bp, const char *function_name,
196 unsigned argc, char **argv)
197{
198 QREncodeContext *qr = ((AVFilterContext *)ctx)->priv;
199 const char *fmt;
200 const char *strftime_fmt = NULL;
201 const char *delta = NULL;
202 double t = qr->var_values[VAR_t];
203
204 // argv: pts, FMT, [DELTA, strftime_fmt]
205
206 fmt = argc >= 1 ? argv[0] : "flt";
207 if (argc >= 2) {
208 delta = argv[1];
209 }
210 if (argc >= 3) {
211 strftime_fmt = argv[2];
212 }
213
214 return ff_print_pts(ctx, bp, t, delta, fmt, strftime_fmt);
215}
216
217static int func_frame_num(void *ctx, AVBPrint *bp, const char *function_name,
218 unsigned argc, char **argv)
219{
220 QREncodeContext *qr = ((AVFilterContext *)ctx)->priv;
221
222 av_bprintf(bp, "%d", (int)V(n));
223 return 0;
224}
225
226static int func_strftime(void *ctx, AVBPrint *bp, const char *function_name,
227 unsigned argc, char **argv)
228{
229 const char *strftime_fmt = argc ? argv[0] : NULL;
230
231 return ff_print_time(ctx, bp, strftime_fmt, !strcmp(function_name, "localtime"));
232}
233
234static int func_frame_metadata(void *ctx, AVBPrint *bp, const char *function_name,
235 unsigned argc, char **argv)
236{
237 QREncodeContext *qr = ((AVFilterContext *)ctx)->priv;
238 AVDictionaryEntry *e = av_dict_get(qr->metadata, argv[0], NULL, 0);
239
240 if (e && e->value)
241 av_bprintf(bp, "%s", e->value);
242 else if (argc >= 2)
243 av_bprintf(bp, "%s", argv[1]);
244
245 return 0;
246}
247
248static int func_eval_expr(void *ctx, AVBPrint *bp, const char *function_name,
249 unsigned argc, char **argv)
250{
251 QREncodeContext *qr = ((AVFilterContext *)ctx)->priv;
252
253 return ff_print_eval_expr(ctx, bp, argv[0],
255 var_names, qr->var_values, &qr->lfg);
256}
257
258static int func_eval_expr_formatted(void *ctx, AVBPrint *bp, const char *function_name,
259 unsigned argc, char **argv)
260{
261 QREncodeContext *qr = ((AVFilterContext *)ctx)->priv;
262 int ret;
263 int positions = -1;
264
265 /*
266 * argv[0] expression to be converted to `int`
267 * argv[1] format: 'x', 'X', 'd' or 'u'
268 * argv[2] positions printed (optional)
269 */
270
271 if (argc == 3) {
272 ret = sscanf(argv[2], "%u", &positions);
273 if (ret != 1) {
274 av_log(ctx, AV_LOG_ERROR, "expr_int_format(): Invalid number of positions"
275 " to print: '%s'\n", argv[2]);
276 return AVERROR(EINVAL);
277 }
278 }
279
280 return ff_print_formatted_eval_expr(ctx, bp, argv[0],
283 &qr->lfg,
284 argv[1][0], positions);
285}
286
288 { "expr", 1, 1, func_eval_expr },
289 { "e", 1, 1, func_eval_expr },
290 { "expr_formatted", 2, 3, func_eval_expr_formatted },
291 { "ef", 2, 3, func_eval_expr_formatted },
292 { "metadata", 1, 2, func_frame_metadata },
293 { "frame_num", 0, 0, func_frame_num },
294 { "n", 0, 0, func_frame_num },
295 { "gmtime", 0, 1, func_strftime },
296 { "localtime", 0, 1, func_strftime },
297 { "pts", 0, 3, func_pts }
298};
299
301{
302 QREncodeContext *qr = ctx->priv;
303 int ret;
304
306
307 qr->qrcode_width = -1;
309
310 if (qr->textfile) {
311 if (qr->text) {
313 "Both text and text file provided. Please provide only one\n");
314 return AVERROR(EINVAL);
315 }
316 if ((ret = ff_load_textfile(ctx, (const char *)qr->textfile, &(qr->text), NULL)) < 0)
317 return ret;
318 }
319
321 .log_ctx = ctx,
322 .functions = expand_text_functions,
324 };
325
327
328 return 0;
329}
330
332{
333 QREncodeContext *qr = ctx->priv;
334
337
339
340 av_freep(&qr->qrcode_data[0]);
342 av_freep(&qr->qrcode_mask_data[0]);
343}
344
345#ifdef DEBUG
346static void show_qrcode(AVFilterContext *ctx, const QRcode *qrcode)
347{
348 int i, j;
349 char *line = av_malloc(qrcode->width + 1);
350 const char *p = qrcode->data;
351
352 if (!line)
353 return;
354 for (i = 0; i < qrcode->width; i++) {
355 for (j = 0; j < qrcode->width; j++)
356 line[j] = (*p++)&1 ? '@' : ' ';
357 line[j] = 0;
358 av_log(ctx, AV_LOG_DEBUG, "%3d: %s\n", i, line);
359 }
360 av_free(line);
361}
362#endif
363
365{
366 QREncodeContext *qr = ctx->priv;
367 struct SwsContext *sws = NULL;
368 QRcode *qrcode = NULL;
369 int i, j;
370 char qrcode_width_changed;
371 int ret;
372 int offset;
373 uint8_t *srcp;
374 uint8_t *dstp0, *dstp;
375
377
378 switch (qr->expansion) {
379 case EXPANSION_NONE:
380 av_bprintf(&qr->expanded_text, "%s", qr->text);
381 break;
382 case EXPANSION_NORMAL:
383 if ((ret = ff_expand_text(&qr->expand_text, qr->text, &qr->expanded_text)) < 0)
384 return ret;
385 break;
386 }
387
388 if (!qr->expanded_text.str || qr->expanded_text.str[0] == 0) {
389 if (qr->is_source) {
391 frame->data, frame->linesize,
393 }
394
395 return 0;
396 }
397
398 av_log(ctx, AV_LOG_DEBUG, "Encoding string '%s'\n", qr->expanded_text.str);
399 qrcode = QRcode_encodeString(qr->expanded_text.str, 1, qr->level, QR_MODE_8,
400 qr->case_sensitive);
401 if (!qrcode) {
402 ret = AVERROR(errno);
404 "Failed to encode string with error \'%s\'\n", av_err2str(ret));
405 goto end;
406 }
407
409 "Encoded QR with width:%d version:%d\n", qrcode->width, qrcode->version);
410#ifdef DEBUG
411 show_qrcode(ctx, (const QRcode *)qrcode);
412#endif
413
414 qrcode_width_changed = qr->qrcode_width != qrcode->width;
415 qr->qrcode_width = qrcode->width;
416
417 // realloc mask if needed
418 if (qrcode_width_changed) {
419 av_freep(&qr->qrcode_mask_data[0]);
421 qrcode->width, qrcode->width,
422 AV_PIX_FMT_GRAY8, 16);
423 if (ret < 0) {
425 "Failed to allocate image for QR code with width %d\n", qrcode->width);
426 goto end;
427 }
428 }
429
430 /* fill mask */
431 dstp0 = qr->qrcode_mask_data[0];
432 srcp = qrcode->data;
433
434 for (i = 0; i < qrcode->width; i++) {
435 dstp = dstp0;
436 for (j = 0; j < qrcode->width; j++)
437 *dstp++ = (*srcp++ & 1) ? 255 : 0;
438 dstp0 += qr->qrcode_mask_linesize[0];
439 }
440
441 if (qr->is_source) {
442 if (qrcode_width_changed) {
443 /* realloc padded image */
444
445 // compute virtual non-rendered padded size
446 // Q/q = W/w
448 ((double)qr->rendered_padded_qrcode_width / qr->rendered_qrcode_width) * qrcode->width;
449
450 av_freep(&qr->qrcode_data[0]);
453 AV_PIX_FMT_ARGB, 16);
454 if (ret < 0) {
456 "Failed to allocate image for QR code with width %d\n",
458 goto end;
459 }
460 }
461
462 /* fill padding */
466
467 /* blend mask */
468 offset = (qr->padded_qrcode_width - qr->qrcode_width) / 2;
472 qr->qrcode_mask_data[0], qr->qrcode_mask_linesize[0], qrcode->width, qrcode->width,
473 3, 0, offset, offset);
474
475 /* scale padded QR over the frame */
476 sws = sws_alloc_context();
477 if (!sws) {
478 ret = AVERROR(ENOMEM);
479 goto end;
480 }
481
482 av_opt_set_int(sws, "srcw", qr->padded_qrcode_width, 0);
483 av_opt_set_int(sws, "srch", qr->padded_qrcode_width, 0);
484 av_opt_set_int(sws, "src_format", AV_PIX_FMT_ARGB, 0);
485 av_opt_set_int(sws, "dstw", qr->rendered_padded_qrcode_width, 0);
486 av_opt_set_int(sws, "dsth", qr->rendered_padded_qrcode_width, 0);
487 av_opt_set_int(sws, "dst_format", frame->format, 0);
488 av_opt_set_int(sws, "sws_flags", SWS_POINT, 0);
489
490 if ((ret = sws_init_context(sws, NULL, NULL)) < 0)
491 goto end;
492
493 sws_scale(sws,
494 (const uint8_t *const *)&qr->qrcode_data, qr->qrcode_linesize,
495 0, qr->padded_qrcode_width,
496 frame->data, frame->linesize);
497 } else {
498#define EVAL_EXPR(name_) \
499 av_expr_eval(qr->name_##_pexpr, qr->var_values, &qr->lfg);
500
501 V(qr_w) = V(w) = qrcode->width;
502
503 V(rendered_qr_w) = V(q) = EVAL_EXPR(rendered_qrcode_width);
504 V(rendered_padded_qr_w) = V(Q) = EVAL_EXPR(rendered_padded_qrcode_width);
505 /* It is necessary if q is expressed from Q */
506 V(rendered_qr_w) = V(q) = EVAL_EXPR(rendered_qrcode_width);
507
508 V(x) = EVAL_EXPR(x);
509 V(y) = EVAL_EXPR(y);
510 /* It is necessary if x is expressed from y */
511 V(x) = EVAL_EXPR(x);
512
514 "Rendering QR code with values n:%d w:%d q:%d Q:%d x:%d y:%d t:%f\n",
515 (int)V(n), (int)V(w), (int)V(q), (int)V(Q), (int)V(x), (int)V(y), V(t));
516
517 /* blend rectangle over the target */
519 frame->data, frame->linesize, frame->width, frame->height,
520 V(x), V(y), V(Q), V(Q));
521
522 if (V(q) != qr->rendered_qrcode_width) {
524 qr->rendered_qrcode_width = V(q);
525
528 AV_PIX_FMT_GRAY8, 16);
529 if (ret < 0) {
531 "Failed to allocate image for rendered QR code with width %d\n",
533 goto end;
534 }
535 }
536
537 /* scale mask */
538 sws = sws_alloc_context();
539 if (!sws) {
540 ret = AVERROR(ENOMEM);
541 goto end;
542 }
543
544 av_opt_set_int(sws, "srcw", qr->qrcode_width, 0);
545 av_opt_set_int(sws, "srch", qr->qrcode_width, 0);
546 av_opt_set_int(sws, "src_format", AV_PIX_FMT_GRAY8, 0);
547 av_opt_set_int(sws, "dstw", qr->rendered_qrcode_width, 0);
548 av_opt_set_int(sws, "dsth", qr->rendered_qrcode_width, 0);
549 av_opt_set_int(sws, "dst_format", AV_PIX_FMT_GRAY8, 0);
550 av_opt_set_int(sws, "sws_flags", SWS_POINT, 0);
551
552 if ((ret = sws_init_context(sws, NULL, NULL)) < 0)
553 goto end;
554
555 sws_scale(sws,
556 (const uint8_t *const *)&qr->qrcode_mask_data, qr->qrcode_mask_linesize,
557 0, qr->qrcode_width,
559
560 /* blend mask over the input frame */
561 offset = (V(Q) - V(q)) / 2;
563 frame->data, frame->linesize, frame->width, frame->height,
566 3, 0, V(x) + offset, V(y) + offset);
567 }
568
569end:
570 sws_freeContext(sws);
571 QRcode_free(qrcode);
572
573 return ret;
574}
575
576#if CONFIG_QRENCODESRC_FILTER
577
580 { "rate", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS },
581 { "r", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS },
582 { NULL }
583};
584
586
588{
589 FilterLink *l = ff_filter_link(outlink);
590 AVFilterContext *ctx = outlink->src;
591 QREncodeContext *qr = ctx->priv;
592 int ret;
593
594 qr->is_source = 1;
595 V(x) = V(y) = 0;
596
597#define PARSE_AND_EVAL_EXPR(var_name_, expr_name_) \
598 ret = av_expr_parse_and_eval(&qr->var_values[VAR_##var_name_], \
599 qr->expr_name_##_expr, \
600 var_names, qr->var_values, \
601 NULL, NULL, \
602 fun2_names, fun2, \
603 &qr->lfg, 0, ctx); \
604 if (ret < 0) { \
605 av_log(ctx, AV_LOG_ERROR, \
606 "Could not evaluate expression '%s'\n", \
607 qr->expr_name_##_expr); \
608 return ret; \
609 }
610
611 /* undefined for the source */
612 V(main_w) = V(W) = NAN;
613 V(main_h) = V(H) = NAN;
614 V(x) = V(y) = V(t) = V(n) = NAN;
615 V(dar) = V(sar) = 1.0;
616
617 PARSE_AND_EVAL_EXPR(rendered_qr_w, rendered_qrcode_width);
618 V(q) = V(rendered_qr_w);
619 PARSE_AND_EVAL_EXPR(rendered_padded_qr_w, rendered_padded_qrcode_width);
620 V(Q) = V(rendered_padded_qr_w);
621 PARSE_AND_EVAL_EXPR(rendered_qr_w, rendered_qrcode_width);
622 V(q) = V(rendered_qr_w);
623
624 qr->rendered_qrcode_width = V(rendered_qr_w);
625 qr->rendered_padded_qrcode_width = V(rendered_padded_qr_w);
626
628 "q:%d Q:%d case_sensitive:%d level:%d\n",
630 qr->case_sensitive, qr->level);
631
634 "Resulting padded QR code width (%d) is lesser than the QR code width (%d)\n",
636 return AVERROR(EINVAL);
637 }
638
640 if (ret < 0) {
641 // This call using constants should not fail. Checking its error code for completeness.
642 av_log(ctx, AV_LOG_ERROR, "Failed to initialize FFDrawContext\n");
643 return ret;
644 }
645 ff_draw_color(&qr->draw, &qr->draw_foreground_color, (const uint8_t *)&qr->foreground_color);
646 ff_draw_color(&qr->draw, &qr->draw_background_color, (const uint8_t *)&qr->background_color);
647
649 if (ret < 0) {
650 av_log(ctx, AV_LOG_ERROR, "Failed to initialize FFDrawContext\n");
651 return ret;
652 }
653 ff_draw_color(&qr->draw0, &qr->draw0_background_color, (const uint8_t *)&qr->background_color);
654
655 outlink->w = qr->rendered_padded_qrcode_width;
656 outlink->h = qr->rendered_padded_qrcode_width;
657 outlink->time_base = av_inv_q(qr->frame_rate);
658 l->frame_rate = qr->frame_rate;
659
660 return 0;
661}
662
663static int request_frame(AVFilterLink *outlink)
664{
665 AVFilterContext *ctx = (AVFilterContext *)outlink->src;
666 QREncodeContext *qr = ctx->priv;
667 AVFrame *frame =
669 int ret;
670
671 if (!frame)
672 return AVERROR(ENOMEM);
673 frame->sample_aspect_ratio = (AVRational) {1, 1};
674 V(n) = frame->pts = qr->pts++;
675 V(t) = qr->pts * av_q2d(outlink->time_base);
676
677 if ((ret = draw_qrcode(ctx, frame)) < 0)
678 return ret;
679
680 return ff_filter_frame(outlink, frame);
681}
682
684 AVFilterFormatsConfig **cfg_in,
685 AVFilterFormatsConfig **cfg_out)
686{
689 AVFilterFormats *fmts = NULL;
690 int ret;
691
692 // this is needed to support both the no-draw and draw cases
693 // for the no-draw case we use FFDrawContext to write on the input picture ref
695 if (ff_draw_init(&draw, pix_fmt, 0) >= 0 &&
697 (ret = ff_add_format(&fmts, pix_fmt)) < 0)
698 return ret;
699
700 return ff_set_common_formats2(ctx, cfg_in, cfg_out, fmts);
701}
702
704 {
705 .name = "default",
706 .type = AVMEDIA_TYPE_VIDEO,
707 .request_frame = request_frame,
708 .config_props = qrencodesrc_config_props,
709 }
710};
711
713 .p.name = "qrencodesrc",
714 .p.description = NULL_IF_CONFIG_SMALL("Generate a QR code."),
715 .p.priv_class = &qrencodesrc_class,
716 .p.inputs = NULL,
717 .priv_size = sizeof(QREncodeContext),
718 .init = init,
719 .uninit = uninit,
722};
723
724#endif // CONFIG_QRENCODESRC_FILTER
725
726#if CONFIG_QRENCODE_FILTER
727
728static const AVOption qrencode_options[] = {
730 {"x", "set x expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, TFLAGS},
731 {"y", "set y expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, TFLAGS},
732 { NULL }
733};
734
736
738{
739 AVFilterContext *ctx = inlink->dst;
740 QREncodeContext *qr = ctx->priv;
741 char *expr;
742 int ret;
743
744 qr->is_source = 0;
745
747 if (ret < 0) {
748 av_log(ctx, AV_LOG_ERROR, "Failed to initialize FFDrawContext\n");
749 return ret;
750 }
751
752 V(W) = V(main_w) = inlink->w;
753 V(H) = V(main_h) = inlink->h;
754 V(sar) = inlink->sample_aspect_ratio.num ? av_q2d(inlink->sample_aspect_ratio) : 1;
755 V(dar) = (double)inlink->w / inlink->h * V(sar);
756 V(hsub) = 1 << qr->draw.hsub_max;
757 V(vsub) = 1 << qr->draw.vsub_max;
758 V(t) = NAN;
759 V(x) = V(y) = NAN;
760
761 qr->x_pexpr = qr->y_pexpr = NULL;
762 qr->x_pexpr = qr->y_pexpr = NULL;
763
764#define PARSE_EXPR(name_) \
765 ret = av_expr_parse(&qr->name_##_pexpr, expr = qr->name_##_expr, var_names, \
766 NULL, NULL, fun2_names, fun2, 0, ctx); \
767 if (ret < 0) { \
768 av_log(ctx, AV_LOG_ERROR, \
769 "Could not to parse expression '%s' for '%s'\n", \
770 expr, #name_); \
771 return AVERROR(EINVAL); \
772 }
773
774 PARSE_EXPR(x);
775 PARSE_EXPR(y);
776 PARSE_EXPR(rendered_qrcode_width);
777 PARSE_EXPR(rendered_padded_qrcode_width);
778
780 if (ret < 0) {
781 av_log(ctx, AV_LOG_ERROR, "Failed to initialize FFDrawContext\n");
782 return ret;
783 }
784 ff_draw_color(&qr->draw, &qr->draw_foreground_color, (const uint8_t *)&qr->foreground_color);
785 ff_draw_color(&qr->draw, &qr->draw_background_color, (const uint8_t *)&qr->background_color);
786
787 qr->rendered_qrcode_width = -1;
788
789 return 0;
790}
791
793 AVFilterFormatsConfig **cfg_in,
794 AVFilterFormatsConfig **cfg_out)
795{
797}
798
800{
801 FilterLink *inl = ff_filter_link(inlink);
802 AVFilterContext *ctx = inlink->dst;
803 AVFilterLink *outlink = ctx->outputs[0];
804 QREncodeContext *qr = ctx->priv;
805 int ret;
806
807 V(n) = inl->frame_count_out;
808 V(t) = frame->pts == AV_NOPTS_VALUE ?
809 NAN : frame->pts * av_q2d(inlink->time_base);
810 V(pict_type) = frame->pict_type;
811 V(duration) = frame->duration * av_q2d(inlink->time_base);
812
813 qr->metadata = frame->metadata;
814
815 if ((ret = draw_qrcode(ctx, frame)) < 0)
816 return ret;
817
818 return ff_filter_frame(outlink, frame);
819}
820
822 {
823 .name = "default",
824 .type = AVMEDIA_TYPE_VIDEO,
826 .filter_frame = filter_frame,
827 .config_props = qrencode_config_input,
828 },
829};
830
832 .p.name = "qrencode",
833 .p.description = NULL_IF_CONFIG_SMALL("Draw a QR code on top of video frames."),
834 .p.priv_class = &qrencode_class,
836 .priv_size = sizeof(QREncodeContext),
837 .init = init,
838 .uninit = uninit,
842};
843
844#endif // CONFIG_QRENCODE_FILTER
static int request_frame(AVFilterLink *outlink)
Definition af_aecho.c:272
#define TFLAGS
Definition af_afade.c:66
const FFFilter ff_vsrc_qrencodesrc
Definition qrencode.c:712
const FFFilter ff_vf_qrencode
Definition qrencode.c:831
static AVFormatContext * ctx
#define V
Definition avdct.c:32
static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
@ VAR_H
Definition avfilter.c:565
@ VAR_W
Definition avfilter.c:564
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition avfilter.c:1068
Main libavfilter public API header.
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition bprint.c:122
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition bprint.c:69
#define AV_BPRINT_SIZE_UNLIMITED
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define FLAGS
Definition cmdutils.c:598
#define NULL
Definition coverity.c:32
#define min(a, b)
#define max(a, b)
static enum AVPixelFormat pix_fmt
static AVFrame * frame
static int filter_frame(DBEDecodeContext *s, AVFrame *frame)
Definition dolby_e.c:1067
void ff_blend_rectangle(FFDrawContext *draw, FFDrawColor *color, uint8_t *dst[], int dst_linesize[], int dst_w, int dst_h, int x0, int y0, int w, int h)
Blend a rectangle with an uniform color.
Definition drawutils.c:378
int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags)
Definition drawutils.c:174
void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4])
Prepare a color.
Definition drawutils.c:179
AVFilterFormats * ff_draw_supported_pixel_formats(unsigned flags)
Return the list of pixel formats supported by the draw functions.
Definition drawutils.c:670
void ff_fill_rectangle(FFDrawContext *draw, FFDrawColor *color, uint8_t *dst[], int dst_linesize[], int dst_x, int dst_y, int w, int h)
Fill a rectangle with an uniform color.
Definition drawutils.c:258
int ff_draw_init_from_link(FFDrawContext *draw, const AVFilterLink *link, unsigned flags)
Init a draw context, taking the format, colorspace and range from the given filter link.
Definition drawutils.c:168
void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color, uint8_t *dst[], int dst_linesize[], int dst_w, int dst_h, const uint8_t *mask, int mask_linesize, int mask_w, int mask_h, int l2depth, unsigned endianness, int x0, int y0)
Blend an alpha mask with an uniform color.
Definition drawutils.c:557
misc drawing utilities
#define FF_DRAW_PROCESS_ALPHA
Process alpha pixel component.
Definition drawutils.h:64
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
void av_expr_free(AVExpr *e)
Free a parsed expression previously created with av_expr_parse().
Definition eval.c:368
#define OFFSET(x)
static int64_t duration
Definition ffplay.c:330
int ff_set_common_formats2(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out, AVFilterFormats *formats)
Definition formats.c:1137
int ff_add_format(AVFilterFormats **avff, int64_t fmt)
Add fmt to the list of media formats contained in *avff.
Definition formats.c:571
@ AV_OPT_TYPE_VIDEO_RATE
Underlying C type is AVRational.
Definition opt.h:314
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition opt.h:275
#define AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
Some filters support a generic "enable" expression option that can be used to enable or disable a fil...
Definition avfilter.h:196
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition bprint.c:235
void av_bprint_clear(AVBPrint *buf)
Reset the string to "" but keep internal allocated data.
Definition bprint.c:227
uint32_t av_get_random_seed(void)
Get a seed to use in conjunction with random functions.
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
Definition dict.c:60
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition error.h:122
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_VERBOSE
Detailed information.
Definition log.h:226
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
static double av_q2d(AVRational a)
Convert an AVRational to a double.
Definition rational.h:104
static av_always_inline AVRational av_inv_q(AVRational q)
Invert a rational.
Definition rational.h:159
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
int av_image_alloc(uint8_t *pointers[4], int linesizes[4], int w, int h, enum AVPixelFormat pix_fmt, int align)
Allocate an image with size w and h and pixel format pix_fmt, and fill pointers and linesizes accordi...
Definition imgutils.c:218
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition avutil.h:247
av_warn_unused_result int sws_init_context(SwsContext *sws_context, SwsFilter *srcFilter, SwsFilter *dstFilter)
Initialize the swscaler context sws_context.
Definition utils.c:1884
SwsContext * sws_alloc_context(void)
Allocate an empty SwsContext and set its fields to default values.
Definition utils.c:1032
int attribute_align_arg sws_scale(SwsContext *sws, const uint8_t *const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[])
swscale wrapper, so we don't need to export the SwsContext.
Definition swscale.c:1626
void sws_freeContext(SwsContext *swsContext)
Free the swscaler context swsContext.
Definition utils.c:2250
@ SWS_POINT
nearest neighbor
Definition swscale.h:201
int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags)
Definition opt.c:934
#define Q(q)
misc image utilities
#define W(a, i, v)
Definition jpegls.h:119
static av_cold void uninit(AVBitStreamFilterContext *ctx)
av_cold void av_lfg_init(AVLFG *c, unsigned int seed)
Definition lfg.c:32
static unsigned int av_lfg_get(AVLFG *c)
Get the next random unsigned 32-bit number using an ALFG.
Definition lfg.h:53
unsigned offset
Definition libaomenc.c:763
#define FILTER_INPUTS(array)
Definition filters.h:264
#define FILTER_OUTPUTS(array)
Definition filters.h:265
#define AVFILTERPAD_FLAG_NEEDS_WRITABLE
The filter expects writable frames from its input link, duplicating data buffers if needed.
Definition filters.h:59
static FilterLink * ff_filter_link(AVFilterLink *link)
Definition filters.h:199
#define AVFILTER_DEFINE_CLASS(fname)
Definition filters.h:478
#define FILTER_QUERY_FUNC2(func)
Definition filters.h:241
#define av_cold
Definition attributes.h:117
common internal API header
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:88
#define COMMON_OPTIONS
Definition libvpxenc.c:1986
uint8_t w
Definition llvidencdsp.c:39
#define NAN
Memory handling functions.
var_name
Definition noise.c:46
@ VAR_VARS_NB
Definition noise.c:59
static const char *const var_names[]
Definition noise.c:30
#define av_malloc(s)
Definition ops_static.c:52
AVOptions.
#define sws_isSupportedOutput(x)
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ AV_PIX_FMT_ARGB
packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
Definition pixfmt.h:99
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition pixfmt.h:81
#define H
Definition pixlet.c:39
static int qrencode_config_input(AVFilterLink *inlink)
Definition qrencode.c:737
@ VAR_hsub
Definition qrencode.c:54
@ VAR_x
Definition qrencode.c:64
@ VAR_dar
Definition qrencode.c:52
@ VAR_q
Definition qrencode.c:61
@ VAR_vsub
Definition qrencode.c:54
@ VAR_qr_w
Definition qrencode.c:59
@ VAR_main_h
Definition qrencode.c:55
@ VAR_duration
Definition qrencode.c:53
@ VAR_rendered_qr_w
Definition qrencode.c:61
@ VAR_y
Definition qrencode.c:65
@ VAR_n
Definition qrencode.c:57
@ VAR_t
Definition qrencode.c:63
@ VAR_main_w
Definition qrencode.c:56
@ VAR_sar
Definition qrencode.c:62
@ VAR_w
Definition qrencode.c:59
@ VAR_VARS_NB
Definition qrencode.c:66
@ VAR_pict_type
Definition qrencode.c:58
@ VAR_Q
Definition qrencode.c:60
@ VAR_rendered_padded_qr_w
Definition qrencode.c:60
static int qrencodesrc_config_props(AVFilterLink *outlink)
Definition qrencode.c:587
static void show_qrcode(AVFilterContext *ctx, const QRcode *qrcode)
Definition qrencode.c:346
static int draw_qrcode(AVFilterContext *ctx, AVFrame *frame)
Definition qrencode.c:364
Expansion
Definition qrencode.c:89
@ EXPANSION_NONE
Definition qrencode.c:90
@ EXPANSION_NORMAL
Definition qrencode.c:91
static int func_eval_expr(void *ctx, AVBPrint *bp, const char *function_name, unsigned argc, char **argv)
Definition qrencode.c:248
static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
Definition qrencode.c:799
static int func_strftime(void *ctx, AVBPrint *bp, const char *function_name, unsigned argc, char **argv)
Definition qrencode.c:226
static int qrencode_query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
Definition qrencode.c:792
static int request_frame(AVFilterLink *outlink)
Definition qrencode.c:663
static const ff_eval_func2 fun2[]
Definition qrencode.c:190
static int func_pts(void *ctx, AVBPrint *bp, const char *function_name, unsigned argc, char **argv)
Definition qrencode.c:195
static const AVOption qrencodesrc_options[]
Definition qrencode.c:578
static const AVFilterPad qrencodesrc_outputs[]
Definition qrencode.c:703
static double drand(void *opaque, double min, double max)
Definition qrencode.c:185
static int func_frame_num(void *ctx, AVBPrint *bp, const char *function_name, unsigned argc, char **argv)
Definition qrencode.c:217
static int func_eval_expr_formatted(void *ctx, AVBPrint *bp, const char *function_name, unsigned argc, char **argv)
Definition qrencode.c:258
static const char *const fun2_names[]
Definition qrencode.c:181
static av_cold void uninit(AVFilterContext *ctx)
Definition qrencode.c:331
static int qrencodesrc_query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
Definition qrencode.c:683
static const AVOption qrencode_options[]
Definition qrencode.c:728
static int func_frame_metadata(void *ctx, AVBPrint *bp, const char *function_name, unsigned argc, char **argv)
Definition qrencode.c:234
static const AVFilterPad avfilter_vf_qrencode_inputs[]
Definition qrencode.c:821
static const FFExpandTextFunction expand_text_functions[]
Definition qrencode.c:287
#define FF_ARRAY_ELEMS(a)
Describe the class of an AVClass context structure.
Definition log.h:76
char * value
Definition dict.h:92
Definition eval.c:171
An instance of a filter.
Definition avfilter.h:273
Lists of formats / etc.
Definition avfilter.h:120
A list of supported formats for one end of a filter link.
Definition formats.h:64
A filter pad used for either input or output.
Definition filters.h:40
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
Context structure for the Lagged Fibonacci PRNG.
Definition lfg.h:33
AVOption.
Definition opt.h:428
Rational number (pair of numerator and denominator).
Definition rational.h:58
int num
Numerator.
Definition rational.h:59
uint8_t vsub_max
Definition drawutils.h:44
uint8_t hsub_max
Definition drawutils.h:43
Text expander context, used to encapsulate the logic to expand a given text template.
Definition textutils.h:66
Function used to expand a template sequence in the format %{FUNCTION_NAME[:PARAMS]}...
Definition textutils.h:36
FFExpandTextContext expand_text
expand text in case expansion is enabled
Definition qrencode.c:142
int qrcode_mask_linesize[4]
Definition qrencode.c:130
int expansion
expansion mode to use for the text
Definition qrencode.c:141
char * y_expr
Definition qrencode.c:99
uint64_t pts
Definition qrencode.c:111
unsigned char * text
Definition qrencode.c:109
char * textfile
Definition qrencode.c:110
AVExpr * rendered_qrcode_width_pexpr
Definition qrencode.c:104
char * rendered_padded_qrcode_width_expr
Definition qrencode.c:103
AVLFG lfg
random generator
Definition qrencode.c:146
uint8_t * qrcode_data[4]
Definition qrencode.c:127
int qrcode_linesize[4]
Definition qrencode.c:128
AVExpr * rendered_padded_qrcode_width_pexpr
Definition qrencode.c:104
AVExpr * x_pexpr
Definition qrencode.c:100
FFDrawColor draw0_background_color
background color
Definition qrencode.c:125
FFDrawColor draw_foreground_color
foreground color
Definition qrencode.c:120
int rendered_qrcode_linesize[4]
Definition qrencode.c:134
FFDrawContext draw
Definition qrencode.c:119
char * x_expr
Definition qrencode.c:98
AVExpr * y_pexpr
Definition qrencode.c:100
FFDrawContext draw0
Definition qrencode.c:124
int rendered_padded_qrcode_width
Definition qrencode.c:107
FFDrawColor draw_background_color
background color
Definition qrencode.c:121
int rendered_qrcode_width
Definition qrencode.c:106
uint8_t background_color[4]
Definition qrencode.c:117
double var_values[VAR_VARS_NB]
Definition qrencode.c:145
AVBPrint expanded_text
used to contain the expanded text
Definition qrencode.c:143
uint8_t * rendered_qrcode_data[4]
Definition qrencode.c:133
int padded_qrcode_width
Definition qrencode.c:137
uint8_t * qrcode_mask_data[4]
Definition qrencode.c:129
AVRational frame_rate
Definition qrencode.c:139
char case_sensitive
Definition qrencode.c:114
AVDictionary * metadata
Definition qrencode.c:147
char * rendered_qrcode_width_expr
Definition qrencode.c:102
uint8_t foreground_color[4]
Definition qrencode.c:116
Main external API structure.
Definition swscale.h:227
external API header
#define av_free(p)
#define av_freep(p)
#define av_log(a,...)
int ff_print_pts(void *log_ctx, AVBPrint *bp, double pts, const char *delta, const char *fmt, const char *strftime_fmt)
Definition textutils.c:150
int ff_load_textfile(void *log_ctx, const char *textfile, unsigned char **text, size_t *text_size)
Definition textutils.c:354
int ff_expand_text(FFExpandTextContext *expand_text, const char *text, AVBPrint *bp)
Expand text template.
Definition textutils.c:124
int ff_print_time(void *log_ctx, AVBPrint *bp, const char *strftime_fmt, char localtime)
Definition textutils.c:203
int ff_print_formatted_eval_expr(void *log_ctx, AVBPrint *bp, const char *expr, const char *const *fun_names, const ff_eval_func2 *fun_values, const char *const *var_names, const double *var_values, void *eval_ctx, const char format, int positions)
Definition textutils.c:304
int ff_print_eval_expr(void *log_ctx, AVBPrint *bp, const char *expr, const char *const *fun_names, const ff_eval_func2 *fun_values, const char *const *var_names, const double *var_values, void *eval_ctx)
Definition textutils.c:282
text utilities
static void hsub(htype *dst, const htype *src, int bins)
Definition vf_median.c:74
#define PARSE_EXPR(e, s)
static const uint16_t positions[][14][3]
const AVFilterPad ff_video_default_filterpad[1]
An AVFilterPad array whose only entry has name "default" and is of type AVMEDIA_TYPE_VIDEO.
Definition video.c:37
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition video.c:89
float delta