1 /*
2  *			GPAC - Multimedia Framework C SDK
3  *
4  *			Authors: Jean Le Feuvre
5  *			Copyright (c) Telecom ParisTech 2017
6  *					All rights reserved
7  *
8  *  This file is part of GPAC / filters sub-project
9  *
10  *  GPAC is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU Lesser General Public License as published by
12  *  the Free Software Foundation; either version 2, or (at your option)
13  *  any later version.
14  *
15  *  GPAC is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU Lesser General Public License for more details.
19  *
20  *  You should have received a copy of the GNU Lesser General Public
21  *  License along with this library; see the file COPYING.  If not, write to
22  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  */
25 
26 #include <gpac/filters.h>
27 #include <gpac/list.h>
28 
29 
30 typedef struct
31 {
32 	u32 opt1;
33 	Bool opt2;
34 
35 	GF_FilterPid *src_pid;
36 	GF_FilterPid *dst_pid;
37 } GF_BaseFilterExample;
38 
example_filter_finalize(GF_Filter * filter)39 static void example_filter_finalize(GF_Filter *filter)
40 {
41 	//peform any finalyze routine needed, including potential free in the filter context
42 	//if not needed, set the filter_finalize to NULL
43 }
example_filter_process(GF_Filter * filter)44 static GF_Err example_filter_process(GF_Filter *filter)
45 {
46 	char *data_dst;
47 	const char *data_src;
48 	u32 size;
49 
50 	GF_FilterPacket *pck_dst;
51 	GF_BaseFilterExample *stack = (GF_BaseFilterExample *) gf_filter_get_udta(filter);
52 
53 	GF_FilterPacket *pck = gf_filter_pid_get_packet(stack->src_pid);
54 	if (!pck) return GF_OK;
55 	data_src = gf_filter_pck_get_data(pck, &size);
56 
57 	//produce output packet using memory allocation
58 	pck_dst = gf_filter_pck_new_alloc(stack->dst_pid, size, &data_dst);
59 	if (!pck_dst) return GF_OUT_OF_MEM;
60 	memcpy(data_dst, data_src, size);
61 
62 	//no need to adjust data framing
63 //	gf_filter_pck_set_framing(pck_dst, GF_TRUE, GF_TRUE);
64 
65 	//copy over src props to dst
66 	gf_filter_pck_merge_properties(pck, pck_dst);
67 	gf_filter_pck_send(pck_dst);
68 
69 	gf_filter_pid_drop_packet(stack->src_pid);
70 	return GF_OK;
71 
72 }
73 
example_filter_config_input(GF_Filter * filter,GF_FilterPid * pid,Bool is_remove)74 static GF_Err example_filter_config_input(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
75 {
76 	const GF_PropertyValue *format;
77 	GF_PropertyValue p;
78 	GF_BaseFilterExample  *stack = (GF_BaseFilterExample *) gf_filter_get_udta(filter);
79 
80 	if (stack->src_pid==pid) {
81 		//disconnect of src pid (not yet supported)
82 		if (is_remove) {
83 		}
84 		//update of caps, check everything is fine
85 		else {
86 		}
87 		return GF_OK;
88 	}
89 	//check input pid properties we are interested in
90 	format = gf_filter_pid_get_property(pid, GF_4CC('c','u','s','t') );
91 	if (!format || !format->value.string || strcmp(format->value.string, "myformat")) {
92 		return GF_NOT_SUPPORTED;
93 	}
94 
95 
96 	//setup output (if we are a filter not a sink)
97 
98 	stack->dst_pid = gf_filter_pid_new(filter);
99 	gf_filter_pid_copy_properties(stack->dst_pid, stack->src_pid);
100 	p.type = GF_PROP_UINT;
101 	p.value.uint = 10;
102 	gf_filter_pid_set_property(stack->dst_pid, GF_4CC('c','u','s','2'), &p);
103 
104 	//set framing mode if needed - by default all PIDs require complete data blocks as inputs
105 //	gf_filter_pid_set_framing_mode(pidctx->src_pid, GF_TRUE);
106 
107 	return GF_OK;
108 }
109 
example_filter_update_arg(GF_Filter * filter,const char * arg_name,const GF_PropertyValue * arg_val)110 static GF_Err example_filter_update_arg(GF_Filter *filter, const char *arg_name, const GF_PropertyValue *arg_val)
111 {
112 	return GF_OK;
113 }
114 
example_filter_initialize(GF_Filter * filter)115 GF_Err example_filter_initialize(GF_Filter *filter)
116 {
117 	GF_BaseFilterExample *stack = gf_filter_get_udta(filter);
118 	if (stack->opt2) {
119 		//do something based on options
120 
121 	}
122 	//if you filter is a source, this is the right place to start declaring output PIDs, such as above
123 
124 	return GF_OK;
125 }
126 
127 #define OFFS(_n)	#_n, offsetof(GF_BaseFilterExample, _n)
128 static const GF_FilterArgs ExampleFilterArgs[] =
129 {
130 	//example uint option using enum, result parsed ranges from 0(=v1) to 2(=v3)
131 	{ OFFS(opt1), "Example option 1", GF_PROP_UINT, "v1", "v1|v2|v3", GF_FALSE},
132 	{ OFFS(opt2), "Example option 2", GF_PROP_BOOL, "false", NULL, GF_FALSE},
133 	{ NULL }
134 };
135 
136 static const GF_FilterCapability ExampleFilterInputs[] =
137 {
138 	{ .cap_string="cust", .val=PROP_NAME("myformat")  },
139 	{ NULL }
140 };
141 
142 static const GF_FilterCapability ExampleFilterOutputs[] =
143 {
144 	{GF_4CC('c','u','s','t'), PROP_UINT(10) },
145 	{ NULL }
146 };
147 
148 const GF_FilterRegister ExampleFilterRegister = {
149 	.name = "ExampleFilter",
150 	.description = "Example Test Filter, not used",
151 	.private_size = sizeof(GF_BaseFilterExample),
152 	.input_caps = ExampleFilterInputs,
153 	.output_caps = ExampleFilterOutputs,
154 	.args = ExampleFilterArgs,
155 	.initialize = example_filter_initialize,
156 	.finalize = example_filter_finalize,
157 	.process = example_filter_process,
158 	.configure_pid = example_filter_config_input,
159 	.update_arg = example_filter_update_arg
160 };
161 
ex_filter_register(GF_FilterSession * session,Bool load_meta_filters)162 const GF_FilterRegister *ex_filter_register(GF_FilterSession *session, Bool load_meta_filters)
163 {
164 	return &ExampleFilterRegister;
165 }
166 
167 
168 
169