File: avfilter.c

package info (click to toggle)
baresip 1.1.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 4,328 kB
  • sloc: ansic: 53,606; cpp: 2,268; makefile: 332; objc: 320; python: 259; sh: 40; xml: 19
file content (166 lines) | stat: -rw-r--r-- 3,041 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/**
 * @file avfilter.c	 Video filter using libavfilter
 *
 * Copyright (C) 2020 Mikhail Kurkov
 */

#include <string.h>
#include <libavformat/avformat.h>
#include <libavfilter/buffersink.h>
#include <libavfilter/buffersrc.h>
#include <libavutil/opt.h>
#include <re.h>
#include <rem.h>
#include <baresip.h>
#include "avfilter.h"

/**
 * @defgroup avfilter avfilter
 *
 * Video filters using libavfilter
 *
 * This module allows to dynamically apply complex video filter graphs
 * to outcoming stream using libavfilter from FFmpeg project.
 *
 * Commands:
 *
 \verbatim
 avfilter <FILTER> - Enable avfilter for outcoming stream
 avfilter          - Disable avfilter
 \endverbatim
 *
 * Example:
 *
 \verbatim
 avfilter movie=watermark.png[pic];[in][pic]overlay=10:10[out]
 \endverbatim
 *
 * References:
 *
 *     https://ffmpeg.org/ffmpeg-filters.html
 *
 */

static struct lock *lock;
static char filter_descr[MAX_DESCR] = "";
static bool filter_updated = false;


static void st_destructor(void *arg)
{
	struct avfilter_st *st = arg;

	list_unlink(&st->vf.le);
	filter_reset(st);
}


static int update(struct vidfilt_enc_st **stp, void **ctx,
		  const struct vidfilt *vf, struct vidfilt_prm *prm,
		  const struct video *vid)
{
	struct avfilter_st *st;
	(void)vid;

	if (!stp || !ctx || !vf || !prm)
		return EINVAL;

	if (*stp)
		return 0;

	st = mem_zalloc(sizeof(*st), st_destructor);
	if (!st)
		return ENOMEM;

	st->enabled = false;

	*stp = (struct vidfilt_enc_st *)st;
	return 0;
}


static int encode(struct vidfilt_enc_st *enc_st, struct vidframe *frame,
		  uint64_t *timestamp)
{
	struct avfilter_st *st = (struct avfilter_st *)enc_st;
	int err;

	if (!frame)
		return 0;

	lock_write_get(lock);
	if (filter_updated || !filter_valid(st, frame)) {
		filter_reset(st);
		filter_init(st, filter_descr, frame);
	}
	filter_updated = false;
	lock_rel(lock);

	err = filter_encode(st, frame, timestamp);

	return err;
}


static int avfilter_command(struct re_printf *pf, void *arg)
{
	const struct cmd_arg *carg = arg;
	(void)pf;

	lock_write_get(lock);

	if (str_isset(carg->prm)) {
		str_ncpy(filter_descr, carg->prm, sizeof(filter_descr));
		info("avfilter: enabled for %s\n", filter_descr);
	}
	else {
		str_ncpy(filter_descr, "", sizeof(filter_descr));
		info("avfilter: disabled\n");
	}

	filter_updated = true;

	lock_rel(lock);
	return 0;
}


static struct vidfilt avfilter = {
	.name    = "avfilter",
	.ench    = encode,
	.encupdh = update
};


static const struct cmd cmdv[] = {
	{"avfilter", 0, CMD_PRM, "Start avfilter", avfilter_command}
};


static int module_init(void)
{
	int err;
	err = lock_alloc(&lock);
	if (err)
		return err;

	vidfilt_register(baresip_vidfiltl(), &avfilter);
	return cmd_register(baresip_commands(), cmdv, ARRAY_SIZE(cmdv));
}


static int module_close(void)
{
	lock = mem_deref(lock);
	vidfilt_unregister(&avfilter);
	cmd_unregister(baresip_commands(), cmdv);
	return 0;
}


EXPORT_SYM const struct mod_export DECL_EXPORTS(avfilter) = {
	"avfilter",
	"vidfilt",
	module_init,
	module_close
};