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