Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2017-2021
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / unit test filters
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 : typedef struct
30 : {
31 : GF_FilterPid *src_pid;
32 : GF_FilterPid *dst_pid;
33 : GF_SHA1Context *sha_ctx;
34 : u32 nb_packets, pck_del;
35 :
36 : GF_FilterFrameInterface frame_ifce;
37 : u8 ifce_data[10];
38 : } PIDCtx;
39 :
40 : enum
41 : {
42 : UTF_MODE_SOURCE=0,
43 : UTF_MODE_SINK,
44 : UTF_MODE_FILTER,
45 : };
46 : typedef struct
47 : {
48 : GF_List *pids;
49 :
50 : //0: source, 1: sink, 2: filter
51 : u32 mode;
52 : u32 max_pck;
53 : s32 max_out;
54 : const char *pid_att;
55 : Bool alloc;
56 : u32 nb_pids;
57 : u32 fwd;
58 : u32 framing;
59 : Bool cov;
60 : Bool norecfg;
61 : const char *update;
62 :
63 : Bool gsftest;
64 : GF_Fraction64 dummy1;
65 : } GF_UnitTestFilter;
66 :
67 23418 : static void test_pck_del(GF_Filter *filter, GF_FilterPid *pid, GF_FilterPacket *pck)
68 : {
69 23418 : PIDCtx *stack = (PIDCtx *) gf_filter_pid_get_udta(pid);
70 23416 : stack->pck_del++;
71 : assert(stack->nb_packets >= stack->pck_del);
72 23416 : GF_LOG(GF_LOG_DEBUG, GF_LOG_APP, ("%s: Packet deleted - %d out there (%d sent %d destroyed)\n", gf_filter_get_name(filter), stack->nb_packets - stack->pck_del, stack->nb_packets, stack->pck_del));
73 23417 : }
74 :
75 :
76 25640 : void dump_properties(GF_FilterPacket *pck, u32 nb_pck)
77 : {
78 25640 : u32 idx = 0;
79 30280 : while (1) {
80 : u32 p4cc;
81 : const char *pname;
82 55920 : const GF_PropertyValue *p = gf_filter_pck_enum_properties(pck, &idx, &p4cc, &pname);
83 55919 : if (!p) break;
84 : //dump_property(pck, nb_pck, p4cc, pname, p);
85 : }
86 25639 : if (nb_pck==1) {
87 212 : gf_filter_pck_get_property(pck, GF_4CC('c','u','s','t'));
88 209 : gf_filter_pck_get_property_str(pck, "custom");
89 : }
90 25640 : }
91 :
92 385 : static void ut_filter_finalize(GF_Filter *filter)
93 : {
94 : u32 i, count;
95 : u8 digest[GF_SHA1_DIGEST_SIZE];
96 385 : GF_UnitTestFilter *stack = (GF_UnitTestFilter *) gf_filter_get_udta(filter);
97 :
98 385 : count = gf_list_count(stack->pids);
99 825 : for (i=0; i<count; i++) {
100 440 : PIDCtx *pidctx = gf_list_get(stack->pids, i);
101 440 : if (pidctx->sha_ctx && (stack->mode!=UTF_MODE_SOURCE) ) {
102 281 : gf_sha1_finish(pidctx->sha_ctx, digest);
103 :
104 281 : if (!pidctx->src_pid) {
105 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[%s] Pid %d Source PID not available while dumping SHA1\n", gf_filter_get_name(filter), i+1 ));
106 : } else {
107 281 : const GF_PropertyValue *p = gf_filter_pid_get_property(pidctx->src_pid, GF_4CC('s','h','a','1') );
108 281 : if (!p) {
109 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[%s] Pid %d sha1 property not found on input pid\n", gf_filter_get_name(filter), i+1 ));
110 281 : } else if (p->value.data.size != GF_SHA1_DIGEST_SIZE) {
111 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[%s] Pid %d wrong size for sha1 property\n", gf_filter_get_name(filter), i+1 ));
112 281 : } else if (memcmp(p->value.data.ptr, digest, p->value.data.size )) {
113 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[%s] Pid %d wrong hash after execution\n", gf_filter_get_name(filter), i+1 ));
114 : } else {
115 281 : GF_LOG(GF_LOG_WARNING, GF_LOG_APP, ("[%s] Pid %d hash OK after execution\n", gf_filter_get_name(filter), i+1 ));
116 : }
117 : }
118 : }
119 440 : gf_free(pidctx);
120 : }
121 385 : gf_list_del(stack->pids);
122 385 : }
123 :
124 21952 : static void ut_filter_send_update(GF_Filter *filter, u32 nb_pck)
125 : {
126 21952 : GF_UnitTestFilter *stack = (GF_UnitTestFilter *) gf_filter_get_udta(filter);
127 :
128 21952 : if (stack->update && (nb_pck==stack->max_pck/2) ) {
129 : char *sep, *fid;
130 9 : char *cmd = gf_strdup(stack->update);
131 : fid = cmd;
132 9 : sep = strchr(cmd, ',');
133 9 : if (sep) {
134 : char *name, *val;
135 9 : sep[0]=0;
136 9 : sep+=1;
137 : name=sep;
138 9 : sep = strchr(name, ',');
139 9 : if (sep) {
140 9 : sep[0]=0;
141 9 : val = sep+1;
142 : } else {
143 : val=NULL;
144 : }
145 9 : gf_filter_send_update(filter, fid, name, val, 0);
146 : }
147 9 : gf_free(cmd);
148 : }
149 21952 : }
150 :
151 :
152 12823 : static GF_Err ut_filter_process_filter(GF_Filter *filter)
153 : {
154 : u32 size, i, j, count, nb_loops;
155 : u32 fwd;
156 : GF_FilterPacket *pck_dst;
157 12823 : GF_UnitTestFilter *stack = (GF_UnitTestFilter *) gf_filter_get_udta(filter);
158 :
159 12823 : count = gf_list_count(stack->pids);
160 20131 : for (i=0; i<count; i++) {
161 12823 : PIDCtx *pidctx = gf_list_get(stack->pids, i);
162 12823 : GF_FilterPacket *pck = gf_filter_pid_get_packet(pidctx->src_pid);
163 12823 : if (!pck)
164 : return GF_OK;
165 :
166 7308 : if ((stack-> max_out>=0) && (pidctx->nb_packets - pidctx->pck_del >= (u32) stack->max_out) ) {
167 0 : GF_LOG(GF_LOG_DEBUG, GF_LOG_APP, ("TestSource: No packets to emit, waiting for destruction\n"));
168 : return GF_OK;
169 : }
170 : }
171 :
172 : //loop on each PID
173 7308 : for (i=0; i<count; i++) {
174 : const u8 *data;
175 : u32 pck_size;
176 : u8 *data_ptr;
177 : u32 data_offset=0;
178 7308 : PIDCtx *pidctx = gf_list_get(stack->pids, i);
179 7308 : GF_FilterPacket *pck = gf_filter_pid_get_packet(pidctx->src_pid);
180 : assert (pck);
181 : assert(pidctx == gf_filter_pid_get_udta(pidctx->src_pid));
182 :
183 7308 : data = gf_filter_pck_get_data(pck, &size);
184 7308 : gf_sha1_update(pidctx->sha_ctx, (u8*)data, size);
185 :
186 7308 : nb_loops = stack->framing ? 3 : 1;
187 7308 : pck_size = stack->framing ? size/nb_loops : size;
188 : data_ptr = (u8 *)data;
189 :
190 14632 : for (j=0; j<nb_loops; j++) {
191 :
192 : //adjust last packet size
193 7324 : if ((j+1) == nb_loops) {
194 7308 : pck_size = size - j*pck_size;
195 : }
196 :
197 7324 : fwd = stack->fwd;
198 7324 : if (fwd==3) fwd = pidctx->nb_packets % 3;
199 :
200 : //shared memory
201 7324 : if (fwd==0) {
202 3269 : pck_dst = gf_filter_pck_new_shared(pidctx->dst_pid, data_ptr, pck_size, test_pck_del);
203 : }
204 : //copy memory
205 4055 : else if (fwd==1) {
206 : u8 *data_dst;
207 2256 : pck_dst = gf_filter_pck_new_alloc(pidctx->dst_pid, pck_size, &data_dst);
208 2256 : if (pck_dst) {
209 2256 : memcpy(data_dst, data_ptr, pck_size);
210 : }
211 : }
212 : //packet reference
213 : else {
214 1799 : if (stack->framing) {
215 8 : pck_dst = gf_filter_pck_new_ref(pidctx->dst_pid, data_offset, pck_size, pck);
216 : } else {
217 1791 : pck_dst = gf_filter_pck_new_ref(pidctx->dst_pid, 0, 0, pck);
218 : }
219 : }
220 :
221 :
222 7324 : if (pck_dst) {
223 : Bool is_start, is_end;
224 : //get source packet framing
225 7324 : gf_filter_pck_get_framing(pck, &is_start, &is_end);
226 : //adjust flags given our framing
227 7324 : if (is_start && j) is_start = GF_FALSE;
228 7324 : if (is_end && (j+1 < nb_loops) ) is_end = GF_FALSE;
229 7324 : if (stack->framing==2) is_start = GF_FALSE;
230 7324 : if (stack->framing==3) is_end = GF_FALSE;
231 :
232 7324 : gf_filter_pck_set_framing(pck_dst, is_start, is_end);
233 :
234 7324 : pidctx->nb_packets++;
235 : //copy over src props to dst
236 7324 : gf_filter_pck_merge_properties(pck, pck_dst);
237 7324 : gf_filter_pck_send(pck_dst);
238 : }
239 : //move our data pointer
240 7324 : data_ptr += pck_size;
241 7324 : data_offset += pck_size;
242 :
243 : } //end framing loop
244 :
245 7308 : gf_filter_pid_drop_packet(pidctx->src_pid);
246 :
247 : } //end PID loop
248 :
249 : return GF_OK;
250 :
251 : }
252 :
253 1 : static void ut_source_pck_del(GF_Filter *filter, GF_FilterPid *pid, GF_FilterPacket *pck)
254 : {
255 :
256 1 : }
257 :
258 1 : static GF_Err ut_source_ifce_get_plane(struct _gf_filter_frame_interface *frame, u32 plane_idx, const u8 **outPlane, u32 *outStride)
259 : {
260 1 : PIDCtx *pctx = frame->user_data;
261 1 : memset(pctx->ifce_data, 0, 10);
262 1 : if (plane_idx) return GF_BAD_PARAM;
263 1 : *outPlane = pctx->ifce_data;
264 1 : *outStride = 5;
265 1 : return GF_OK;
266 : }
267 :
268 22083 : static GF_Err ut_filter_process_source(GF_Filter *filter)
269 : {
270 : GF_PropertyValue p;
271 : GF_FilterPacket *pck;
272 : u32 i, count, nb_eos;
273 22083 : GF_UnitTestFilter *stack = (GF_UnitTestFilter *) gf_filter_get_udta(filter);
274 :
275 : nb_eos = 0;
276 22083 : count = gf_list_count(stack->pids);
277 44317 : for (i=0; i<count; i++) {
278 22234 : PIDCtx *pidctx=gf_list_get(stack->pids, i);
279 :
280 22234 : if (pidctx->nb_packets==stack->max_pck) {
281 282 : if (stack->gsftest) {
282 2 : if (pidctx->dst_pid) {
283 1 : gf_filter_pid_remove(pidctx->dst_pid);
284 1 : pidctx->dst_pid = NULL;
285 : }
286 : }
287 282 : nb_eos++;
288 282 : continue;
289 : }
290 :
291 21952 : if ((stack->max_out>=0) && (pidctx->nb_packets - pidctx->pck_del >= (u32) stack->max_out) ) {
292 0 : GF_LOG(GF_LOG_DEBUG, GF_LOG_APP, ("TestSource: No packets to emit, waiting for destruction\n"));
293 0 : continue;
294 : }
295 21952 : pidctx->nb_packets++;
296 :
297 21952 : if (stack->gsftest && pidctx->nb_packets==4) {
298 1 : pidctx->frame_ifce.get_plane = ut_source_ifce_get_plane;
299 1 : pidctx->frame_ifce.user_data = pidctx;
300 1 : pck = gf_filter_pck_new_frame_interface(pidctx->dst_pid, &pidctx->frame_ifce, ut_source_pck_del);
301 21951 : } else if (stack->alloc) {
302 : u8 *data;
303 1800 : pck = gf_filter_pck_new_alloc(pidctx->dst_pid, 10, &data);
304 1800 : memcpy(data, "PacketCopy", 10);
305 1800 : gf_sha1_update(pidctx->sha_ctx, "PacketCopy", 10);
306 : } else {
307 20151 : pck = gf_filter_pck_new_shared(pidctx->dst_pid, "PacketShared", 12, test_pck_del);
308 20151 : gf_sha1_update(pidctx->sha_ctx, "PacketShared", 12);
309 : }
310 21952 : GF_LOG(GF_LOG_DEBUG, GF_LOG_APP, ("TestSource: pck %d PacketShared\n", pidctx->nb_packets));
311 :
312 21952 : gf_filter_pck_set_cts(pck, pidctx->nb_packets);
313 :
314 21952 : p.type = GF_PROP_NAME;
315 21952 : p.value.string = "custom_value";
316 21952 : gf_filter_pck_set_property(pck, GF_4CC('c','u','s','t'), &p);
317 :
318 : //try all our properties
319 21952 : if (pidctx->nb_packets==1) {
320 159 : u32 val=1;
321 159 : gf_filter_pck_set_property(pck, GF_4CC('c','u','s','1'), &PROP_BOOL(GF_TRUE) );
322 159 : gf_filter_pck_set_property(pck, GF_4CC('c','u','s','2'), &PROP_SINT(-1));
323 159 : gf_filter_pck_set_property(pck, GF_4CC('c','u','s','3'), &PROP_UINT(1));
324 159 : gf_filter_pck_set_property(pck, GF_4CC('c','u','s','4'), &PROP_LONGSINT(-1));
325 159 : gf_filter_pck_set_property(pck, GF_4CC('c','u','s','5'), &PROP_LONGUINT(1));
326 159 : gf_filter_pck_set_property(pck, GF_4CC('c','u','s','6'), &PROP_FLOAT(1.0f));
327 159 : gf_filter_pck_set_property(pck, GF_4CC('c','u','s','7'), &PROP_DOUBLE(1.0));
328 159 : gf_filter_pck_set_property(pck, GF_4CC('c','u','s','8'), &PROP_FRAC_INT(1,1));
329 159 : gf_filter_pck_set_property(pck, GF_4CC('c','u','s','8'), &PROP_FRAC64_INT(1,1));
330 159 : gf_filter_pck_set_property(pck, GF_4CC('c','u','s','9'), &PROP_POINTER(pck));
331 :
332 159 : if (stack->gsftest) {
333 1 : gf_filter_pck_set_property(pck, GF_4CC('c','u','s','a'), &PROP_DATA(pidctx->ifce_data, 8));
334 1 : gf_filter_pck_set_property(pck, GF_4CC('c','u','s','b'), &PROP_CONST_DATA(pidctx->ifce_data, 8));
335 : } else {
336 158 : gf_filter_pck_set_property(pck, GF_4CC('c','u','s','a'), &PROP_DATA((char *) pidctx, sizeof(pidctx)));
337 158 : gf_filter_pck_set_property(pck, GF_4CC('c','u','s','b'), &PROP_CONST_DATA((char *) pidctx, sizeof(pidctx)));
338 : }
339 159 : gf_filter_pck_set_property(pck, GF_4CC('c','u','s','c'), &PROP_STRING("custom"));
340 159 : gf_filter_pck_set_property(pck, GF_4CC('c','u','s','d'), &PROP_STRING("custom"));
341 : memset(&p, 0, sizeof(GF_PropertyValue));
342 159 : p.type = GF_PROP_VEC2;
343 159 : gf_filter_pck_set_property(pck, GF_4CC('c','u','s','e'), &p);
344 159 : p.type = GF_PROP_VEC2I;
345 159 : gf_filter_pck_set_property(pck, GF_4CC('c','u','s','f'), &p);
346 159 : p.type = GF_PROP_VEC3I;
347 159 : gf_filter_pck_set_property(pck, GF_4CC('c','u','s','h'), &p);
348 159 : p.type = GF_PROP_VEC4I;
349 159 : gf_filter_pck_set_property(pck, GF_4CC('c','u','s','j'), &p);
350 159 : p.type = GF_PROP_STRING_LIST;
351 159 : p.value.string_list.nb_items = 1;
352 159 : p.value.string_list.vals = gf_malloc(sizeof(char *));
353 159 : p.value.string_list.vals[0] = gf_strdup("custom");
354 159 : gf_filter_pck_set_property(pck, GF_4CC('c','u','s','k'), &p);
355 159 : p.type = GF_PROP_UINT_LIST;
356 159 : p.value.uint_list.nb_items = 1;
357 159 : p.value.uint_list.vals = &val;
358 159 : gf_filter_pck_set_property(pck, GF_4CC('c','u','s','l'), &p);
359 :
360 159 : gf_filter_pck_set_property_str(pck, "cusd", &PROP_BOOL(GF_TRUE) );
361 159 : gf_filter_pck_set_property_dyn(pck, "cuse", &PROP_BOOL(GF_TRUE) );
362 : }
363 21952 : if (stack->gsftest) {
364 1000 : gf_filter_pck_set_dts(pck, pidctx->nb_packets-1);
365 1000 : gf_filter_pck_set_cts(pck, pidctx->nb_packets-1);
366 1000 : gf_filter_pck_set_duration(pck, 1);
367 1000 : if (pidctx->nb_packets==2) {
368 1 : gf_filter_pck_set_seek_flag(pck, GF_TRUE);
369 1 : gf_filter_pck_set_carousel_version(pck, 1);
370 1 : gf_filter_pck_set_interlaced(pck, GF_TRUE);
371 1 : gf_filter_pck_set_sap(pck, GF_FILTER_SAP_3);
372 1 : gf_filter_pck_set_dependency_flags(pck, 0xFF);
373 1 : gf_filter_pck_set_property(pck, GF_PROP_PCK_SENDER_NTP, &PROP_LONGUINT(0) );
374 : }
375 999 : else if (pidctx->nb_packets==3) {
376 1 : gf_filter_pck_set_sap(pck, GF_FILTER_SAP_4);
377 1 : gf_filter_pck_set_roll_info(pck, 1);
378 1 : gf_filter_pck_set_byte_offset(pck, 20);
379 : }
380 : }
381 :
382 21952 : ut_filter_send_update(filter, pidctx->nb_packets);
383 :
384 21952 : if (pidctx->nb_packets==stack->max_pck) {
385 159 : if (pidctx->sha_ctx) {
386 : u8 digest[GF_SHA1_DIGEST_SIZE];
387 159 : gf_sha1_finish(pidctx->sha_ctx, digest);
388 159 : pidctx->sha_ctx = NULL;
389 159 : p.type = GF_PROP_DATA;
390 159 : p.value.data.size = GF_SHA1_DIGEST_SIZE;
391 159 : p.value.data.ptr = (char *) digest;
392 : //with this we test both:
393 : //- SHA of send data is correct at the receiver side
394 : //- property update on a PID
395 159 : gf_filter_pid_set_property(pidctx->dst_pid, GF_4CC('s','h','a','1'), &p);
396 : }
397 : }
398 : //just for coverage: check keeping a reference to the packet
399 21952 : gf_filter_pck_ref(& pck);
400 :
401 21952 : gf_filter_pck_send(pck);
402 :
403 : //and destroy the reference
404 21952 : gf_filter_pck_unref(pck);
405 :
406 : }
407 22083 : if (nb_eos==count) return GF_EOS;
408 21880 : return GF_OK;
409 : }
410 :
411 :
412 25850 : static GF_Err ut_filter_process_sink(GF_Filter *filter)
413 : {
414 : u32 size, i, count, nb_eos;
415 : const char *data;
416 25850 : GF_UnitTestFilter *stack = (GF_UnitTestFilter *) gf_filter_get_udta(filter);
417 :
418 25850 : count = gf_list_count(stack->pids);
419 : nb_eos=0;
420 :
421 55719 : for (i=0; i<count; i++) {
422 29869 : PIDCtx *pidctx=gf_list_get(stack->pids, i);
423 :
424 29869 : GF_FilterPacket *pck = gf_filter_pid_get_packet(pidctx->src_pid);
425 29869 : if (!pck) {
426 4230 : if (gf_filter_pid_is_eos(pidctx->src_pid)) nb_eos++;
427 4230 : continue;
428 : }
429 :
430 25639 : data = gf_filter_pck_get_data(pck, &size);
431 :
432 25639 : if (stack->cov && !pidctx->nb_packets) {
433 : GF_PropertyValue p;
434 2 : Bool old_strict = gf_log_set_strict_error(GF_FALSE);
435 2 : gf_filter_pck_send(pck);
436 2 : gf_filter_pck_set_property(pck, GF_4CC('c','u','s','t'), &p);
437 2 : gf_filter_pck_merge_properties(pck, pck);
438 2 : gf_filter_pck_set_framing(pck, GF_TRUE, GF_FALSE);
439 2 : gf_log_set_strict_error(old_strict);
440 : }
441 :
442 25639 : gf_sha1_update(pidctx->sha_ctx, (u8*)data, size);
443 :
444 25640 : pidctx->nb_packets++;
445 25640 : GF_LOG(GF_LOG_DEBUG, GF_LOG_APP, ("TestSink: Consuming packet %d bytes\n", size));
446 :
447 25640 : dump_properties(pck, pidctx->nb_packets);
448 :
449 25640 : gf_filter_pid_drop_packet(pidctx->src_pid);
450 :
451 : } //end PID loop
452 :
453 25850 : if (nb_eos==count) return GF_EOS;
454 :
455 25850 : return GF_OK;
456 : }
457 :
458 :
459 558 : static GF_Err ut_filter_config_input(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
460 : {
461 : const GF_PropertyValue *format;
462 : GF_PropertyValue p;
463 : PIDCtx *pidctx;
464 : u32 i, count;
465 558 : GF_UnitTestFilter *stack = (GF_UnitTestFilter *) gf_filter_get_udta(filter);
466 :
467 559 : if (stack->mode==UTF_MODE_SOURCE) {
468 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error: Attempt to connect PID on source filter\n"));
469 : return GF_BAD_PARAM;
470 : }
471 : //for both filter and sink modes, check input format
472 :
473 559 : count = gf_list_count(stack->pids);
474 632 : for (i=0; i<count; i++) {
475 351 : pidctx = gf_list_get(stack->pids, i);
476 :
477 : //something is being reconfigured. We check we have the same custum arg, otherwise we do not support
478 353 : if (pidctx->src_pid == pid) {
479 279 : format = gf_filter_pid_get_property(pidctx->src_pid, GF_4CC('c','u','s','t') );
480 279 : if (!format || !format->value.string || strcmp(format->value.string, stack->pid_att)) {
481 : return GF_NOT_SUPPORTED;
482 : }
483 : //filter mode, set properties on output
484 279 : if (stack->mode==UTF_MODE_FILTER) {
485 : //this is not needed since copy_properties does that, used for coverage/tests
486 68 : gf_filter_pid_reset_properties(pidctx->dst_pid);
487 68 : gf_filter_pid_copy_properties(pidctx->dst_pid, pidctx->src_pid);
488 : }
489 : return GF_OK;
490 : }
491 : }
492 :
493 : //check our functions
494 281 : format = gf_filter_pid_get_property_str(pid, "custom1");
495 281 : if (!format) {
496 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("%s: expecting property string custom1 on PID\n", gf_filter_get_name(filter) ));
497 : }
498 281 : format = gf_filter_pid_get_property_str(pid, "custom2");
499 281 : if (!format) {
500 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("%s: expecting property string custom2 on PID\n", gf_filter_get_name(filter) ));
501 : }
502 :
503 281 : format = gf_filter_pid_get_property(pid, GF_4CC('c','u','s','t') );
504 281 : if (!format || !format->value.string || strcmp(format->value.string, stack->pid_att)) {
505 : return GF_NOT_SUPPORTED;
506 : }
507 :
508 : //new PID
509 281 : GF_SAFEALLOC(pidctx, PIDCtx);
510 281 : if (!pidctx) return GF_OUT_OF_MEM;
511 281 : pidctx->src_pid = pid;
512 281 : gf_list_add(stack->pids, pidctx);
513 : assert(pidctx->src_pid);
514 :
515 : //coverage mode
516 281 : if (stack->cov) {
517 : u8 *data;
518 3 : Bool old_strict = gf_log_set_strict_error(GF_FALSE);
519 3 : gf_filter_pid_set_property(pidctx->src_pid, GF_4CC('s','h','a','1'), format);
520 3 : gf_filter_pid_reset_properties(pidctx->src_pid);
521 3 : gf_filter_pck_new_alloc(pidctx->src_pid, 20, &data);
522 3 : gf_filter_pck_new_shared(pidctx->src_pid, "foo", 3, NULL);
523 3 : gf_filter_pck_new_ref(pidctx->src_pid, 0, 3, NULL);
524 3 : gf_log_set_strict_error(old_strict);
525 : }
526 :
527 : //filter mode, setup output
528 281 : if (stack->mode==UTF_MODE_FILTER) {
529 68 : pidctx->dst_pid = gf_filter_pid_new(filter);
530 68 : p.type=GF_PROP_NAME;
531 68 : p.value.string = (char *) stack->pid_att;
532 68 : gf_filter_pid_copy_properties(pidctx->dst_pid, pidctx->src_pid);
533 :
534 68 : if (stack->cov) {
535 1 : Bool old_strict = gf_log_set_strict_error(GF_FALSE);
536 1 : gf_filter_pid_copy_properties(pidctx->src_pid, pidctx->dst_pid);
537 1 : gf_filter_pid_get_packet(pidctx->dst_pid);
538 1 : gf_filter_pid_drop_packet(pidctx->dst_pid);
539 1 : gf_filter_pid_drop_packet(pidctx->src_pid);
540 1 : gf_log_set_strict_error(old_strict);
541 : }
542 :
543 68 : gf_filter_pid_set_property(pidctx->dst_pid, GF_4CC('c','u','s','t'), &p);
544 :
545 68 : gf_filter_pid_set_udta(pidctx->dst_pid, pidctx);
546 68 : gf_filter_pid_set_udta(pidctx->src_pid, pidctx);
547 :
548 68 : gf_filter_pid_set_framing_mode(pidctx->src_pid, GF_TRUE);
549 68 : pidctx->sha_ctx = gf_sha1_starts();
550 : }
551 : //sink mode, request full reconstruction of input blocks or not depending on framing mode
552 : else {
553 : GF_FilterEvent evt;
554 213 : gf_filter_pid_set_framing_mode(pidctx->src_pid, stack->framing ? GF_FALSE : GF_TRUE);
555 212 : pidctx->sha_ctx = gf_sha1_starts();
556 213 : GF_FEVT_INIT(evt, GF_FEVT_PLAY, pid);
557 213 : gf_filter_pid_send_event(pid, &evt);
558 : }
559 :
560 : return GF_OK;
561 : }
562 :
563 :
564 141 : static GF_Err ut_filter_config_source(GF_Filter *filter)
565 : {
566 : GF_PropertyValue p;
567 : PIDCtx *pidctx;
568 : u32 i;
569 141 : GF_UnitTestFilter *stack = (GF_UnitTestFilter *) gf_filter_get_udta(filter);
570 :
571 300 : for (i=0; i<stack->nb_pids; i++) {
572 : //create a pid
573 159 : GF_SAFEALLOC(pidctx, PIDCtx);
574 159 : if (!pidctx) return GF_OUT_OF_MEM;
575 159 : gf_list_add(stack->pids, pidctx);
576 159 : pidctx->dst_pid = gf_filter_pid_new(filter);
577 159 : gf_filter_pid_set_udta(pidctx->dst_pid, pidctx);
578 :
579 : //set a custum property
580 159 : p.type = GF_PROP_NAME;
581 159 : p.value.string = (char *) stack->pid_att;
582 159 : gf_filter_pid_set_property(pidctx->dst_pid, GF_4CC('c','u','s','t'), &p);
583 :
584 : //for coverage
585 159 : gf_filter_pid_set_property_str(pidctx->dst_pid, "custom1", &p);
586 159 : gf_filter_pid_set_property_dyn(pidctx->dst_pid, "custom2", &p);
587 :
588 159 : if (stack->cov) {
589 1 : Bool old_strict = gf_log_set_strict_error(GF_FALSE);
590 1 : gf_filter_pid_set_framing_mode(pidctx->dst_pid, GF_TRUE);
591 1 : gf_log_set_strict_error(old_strict);
592 : }
593 :
594 159 : pidctx->sha_ctx = gf_sha1_starts();
595 :
596 159 : if (stack->gsftest) {
597 1 : gf_filter_pid_set_property(pidctx->dst_pid, GF_PROP_PID_STREAM_TYPE, &PROP_UINT(GF_STREAM_VISUAL) );
598 1 : gf_filter_pid_set_property(pidctx->dst_pid, GF_PROP_PID_WIDTH, &PROP_UINT(5) );
599 1 : gf_filter_pid_set_property(pidctx->dst_pid, GF_PROP_PID_HEIGHT, &PROP_UINT(2) );
600 1 : gf_filter_pid_set_property(pidctx->dst_pid, GF_PROP_PID_FPS, &PROP_FRAC_INT(25,1) );
601 1 : gf_filter_pid_set_property(pidctx->dst_pid, GF_PROP_PID_CODECID, &PROP_UINT(GF_CODECID_RAW) );
602 1 : gf_filter_pid_set_property(pidctx->dst_pid, GF_PROP_PID_PIXFMT, &PROP_UINT(GF_PIXEL_GREYSCALE) );
603 1 : gf_filter_pid_set_property_str(pidctx->dst_pid, "gsfdummy", &p);
604 1 : gf_filter_pid_set_property(pidctx->dst_pid, GF_PROP_PID_TIMESCALE, &PROP_UINT(25) );
605 : }
606 :
607 : }
608 : return GF_OK;
609 : }
610 :
611 :
612 9 : static GF_Err ut_filter_update_arg(GF_Filter *filter, const char *arg_name, const GF_PropertyValue *arg_val)
613 : {
614 9 : return GF_OK;
615 : }
616 :
617 385 : GF_Err utfilter_initialize(GF_Filter *filter)
618 : {
619 : GF_PropertyValue p;
620 385 : GF_UnitTestFilter *stack = gf_filter_get_udta(filter);
621 :
622 385 : stack->pids = gf_list_new();
623 :
624 385 : if (stack->cov) {
625 : Bool old_strict;
626 : char szFmt[40];
627 : s64 val;
628 : u32 i;
629 : GF_PropertyValue p2;
630 3 : p = gf_props_parse_value(GF_PROP_BOOL, "prop", "true", NULL, 0);
631 3 : if (p.value.boolean != GF_TRUE) {
632 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing boolean value\n"));
633 : }
634 3 : p = gf_props_parse_value(GF_PROP_BOOL, "prop", "yes", NULL, 0);
635 3 : if (p.value.boolean != GF_TRUE) {
636 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing boolean value\n"));
637 : }
638 3 : p = gf_props_parse_value(GF_PROP_BOOL, "prop", "no", NULL, 0);
639 3 : if (p.value.boolean != GF_FALSE) {
640 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing boolean value\n"));
641 : }
642 3 : p = gf_props_parse_value(GF_PROP_BOOL, "prop", "false", NULL, 0);
643 3 : if (p.value.boolean != GF_FALSE) {
644 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing boolean value\n"));
645 : }
646 3 : p = gf_props_parse_value(GF_PROP_SINT, "prop", "-1", NULL, 0);
647 3 : if (p.value.sint != -1) {
648 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing sint value\n"));
649 : }
650 3 : p = gf_props_parse_value(GF_PROP_SINT, "prop", "-1k", NULL, 0);
651 3 : if (p.value.sint != -1000) {
652 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing sint value\n"));
653 : }
654 3 : p = gf_props_parse_value(GF_PROP_UINT, "prop", "1", NULL, 0);
655 3 : if (p.value.uint != 1) {
656 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing uint value\n"));
657 : }
658 3 : p = gf_props_parse_value(GF_PROP_UINT, "prop", "1m", NULL, 0);
659 3 : if (p.value.uint != 1000000) {
660 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing uint 1m value\n"));
661 : }
662 3 : p = gf_props_parse_value(GF_PROP_UINT, "prop", "0x10000000", NULL, 0);
663 3 : if (p.value.uint != 0x10000000) {
664 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing uint hex value\n"));
665 : }
666 3 : p = gf_props_parse_value(GF_PROP_UINT, "prop", "moof", NULL, 0);
667 3 : if (p.value.uint != GF_4CC('m','o','o','f')) {
668 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing uint 4CC value\n"));
669 : }
670 : val = 0xFFFFFFFF;
671 : val *= 2;
672 : sprintf(szFmt, ""LLD, -val);
673 3 : p = gf_props_parse_value(GF_PROP_LSINT, "prop", szFmt, NULL, 0);
674 3 : if (p.value.longsint != -val) {
675 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing longsint value\n"));
676 : }
677 3 : p = gf_props_parse_value(GF_PROP_LSINT, "prop", "-1m", NULL, 0);
678 3 : if (p.value.longsint != -1000000) {
679 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing longsint value\n"));
680 : }
681 : sprintf(szFmt, ""LLU, val);
682 3 : p = gf_props_parse_value(GF_PROP_LUINT, "prop", szFmt, NULL, 0);
683 3 : if (p.value.longuint != val) {
684 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing longuint value\n"));
685 : }
686 3 : p = gf_props_parse_value(GF_PROP_LUINT, "prop", "1k", NULL, 0);
687 3 : if (p.value.longuint != 1000) {
688 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing longuint value\n"));
689 : }
690 3 : p = gf_props_parse_value(GF_PROP_FLOAT, "prop", "1.0", NULL, 0);
691 3 : if (p.value.fnumber != FIX_ONE) {
692 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing float value\n"));
693 : }
694 3 : p = gf_props_parse_value(GF_PROP_DOUBLE, "prop", "1.0", NULL, 0);
695 3 : if (p.value.number != 1.0) {
696 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing double value\n"));
697 : }
698 3 : p = gf_props_parse_value(GF_PROP_DOUBLE, "prop", "1.0m", NULL, 0);
699 3 : if (p.value.number != 1000000.0) {
700 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing double value\n"));
701 : }
702 3 : p = gf_props_parse_value(GF_PROP_FRACTION, "prop", "1000/1", NULL, 0);
703 3 : if ((p.value.frac.den != 1) || (p.value.frac.num != 1000)) {
704 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing fraction value\n"));
705 : }
706 3 : p = gf_props_parse_value(GF_PROP_FRACTION, "prop", "1000", NULL, 0);
707 3 : if ((p.value.frac.den != 1) || (p.value.frac.num != 1000)) {
708 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing fraction value\n"));
709 : }
710 3 : p = gf_props_parse_value(GF_PROP_FRACTION, "prop", "1.001", NULL, 0);
711 3 : if (p.value.frac.num * 1000 != 1001 * p.value.frac.den) {
712 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing fraction fp value\n"));
713 : }
714 3 : p = gf_props_parse_value(GF_PROP_STRING, "prop", "test", NULL, 0);
715 3 : if (!p.value.string || strcmp(p.value.string, "test")) {
716 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing fraction value\n"));
717 : }
718 3 : if (p.value.string) gf_free(p.value.string);
719 :
720 3 : p = gf_props_parse_value(GF_PROP_FRACTION64, "prop", "1.001", NULL, 0);
721 3 : if (p.value.lfrac.num * 1000 != p.value.lfrac.den * 1001) {
722 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing fraction64 fp value\n"));
723 : }
724 3 : p = gf_props_parse_value(GF_PROP_VEC2I, "prop", "1x1", NULL, 0);
725 3 : if ((p.value.vec2i.x != 1) || (p.value.vec2i.y != 1) ) {
726 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing vec2i value\n"));
727 : }
728 3 : p = gf_props_parse_value(GF_PROP_VEC2, "prop", "1x1", NULL, 0);
729 3 : if ((p.value.vec2.x != 1.0) || (p.value.vec2.y != 1.0) ) {
730 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing vec2 value\n"));
731 : }
732 3 : p = gf_props_parse_value(GF_PROP_VEC3I, "prop", "1x1x1", NULL, 0);
733 3 : if ((p.value.vec3i.x != 1) || (p.value.vec3i.y != 1) || (p.value.vec3i.z != 1)) {
734 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing vec3i value\n"));
735 : }
736 3 : p = gf_props_parse_value(GF_PROP_VEC4I, "prop", "1x1x1x1", NULL, 0);
737 3 : if ((p.value.vec4i.x != 1) || (p.value.vec4i.y != 1) || (p.value.vec4i.z != 1) || (p.value.vec4i.w != 1)) {
738 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing vec4i value\n"));
739 : }
740 3 : p = gf_props_parse_value(GF_PROP_PIXFMT, "prop", "rgb", NULL, 0);
741 3 : if (p.value.uint != GF_PIXEL_RGB) {
742 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing pixfmt value\n"));
743 : }
744 3 : p = gf_props_parse_value(GF_PROP_PCMFMT, "prop", "pcm", NULL, 0);
745 3 : if (p.value.uint != GF_AUDIO_FMT_S16) {
746 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing pcmfmt value\n"));
747 : }
748 :
749 : sprintf(szFmt, "%d@%p", (u32) sizeof(stack), stack);
750 3 : p = gf_props_parse_value(GF_PROP_DATA, "prop", szFmt, NULL, 0);
751 3 : if ((p.value.data.size != (u32) sizeof(stack)) || memcmp(p.value.data.ptr, (char *) stack, sizeof(stack))) {
752 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing data value\n"));
753 : }
754 3 : p = gf_props_parse_value(GF_PROP_CONST_DATA, "prop", szFmt, NULL, 0);
755 3 : if ((p.value.data.ptr != (u8 *) stack) || (p.value.data.size != (u32) sizeof(stack))) {
756 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing data value\n"));
757 : }
758 3 : p = gf_props_parse_value(GF_PROP_CONST_DATA, "prop", "0xABCDEF", NULL, 0);
759 3 : if (!p.value.data.ptr || (p.value.data.size != 3) || (p.value.data.ptr[0] != 0xAB) ) {
760 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing data value\n"));
761 : }
762 3 : if (p.value.data.ptr) gf_free(p.value.data.ptr);
763 :
764 : sprintf(szFmt, "%p", stack);
765 3 : p = gf_props_parse_value(GF_PROP_POINTER, "prop", szFmt, NULL, 0);
766 3 : if (p.value.ptr != stack) {
767 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("[UTFilter] Error parsing data value\n"));
768 : }
769 :
770 3 : old_strict = gf_log_set_strict_error(GF_FALSE);
771 : //negative tests
772 3 : gf_props_parse_value(GF_PROP_STRING, "prop", "file@_no_exist", NULL, 0);
773 3 : gf_props_parse_value(GF_PROP_STRING, "prop", "bxml@_no_exist", NULL, 0);
774 3 : gf_props_parse_value(GF_PROP_DATA, "prop", "file@_no_exist", NULL, 0);
775 3 : gf_props_parse_value(GF_PROP_DATA, "prop", "bxml@_no_exist", NULL, 0);
776 3 : gf_props_parse_value(GF_PROP_BOOL, "prop", "", NULL, 0);
777 3 : gf_props_parse_value(GF_PROP_SINT, "prop", "", NULL, 0);
778 3 : gf_props_parse_value(GF_PROP_UINT, "prop", "", NULL, 0);
779 3 : gf_props_parse_value(GF_PROP_LSINT, "prop", "", NULL, 0);
780 3 : gf_props_parse_value(GF_PROP_LUINT, "prop", "", NULL, 0);
781 3 : gf_props_parse_value(GF_PROP_FLOAT, "prop", "", NULL, 0);
782 3 : gf_props_parse_value(GF_PROP_DOUBLE, "prop", "", NULL, 0);
783 3 : gf_props_parse_value(GF_PROP_FRACTION, "prop", "", NULL, 0);
784 3 : gf_props_parse_value(GF_PROP_FRACTION, "prop", "", NULL, 0);
785 3 : gf_props_parse_value(GF_PROP_STRING, "prop", NULL, NULL, 0);
786 3 : gf_props_parse_value(GF_PROP_DATA, "prop", "", NULL, 0);
787 3 : gf_props_parse_value(GF_PROP_CONST_DATA, "prop", "", NULL, 0);
788 3 : gf_props_parse_value(GF_PROP_POINTER, "prop", "", NULL, 0);
789 3 : gf_props_parse_value(GF_PROP_BOOL, "prop", NULL, NULL, 0);
790 3 : gf_props_parse_value(GF_PROP_SINT, "prop", NULL, NULL, 0);
791 3 : gf_props_parse_value(GF_PROP_UINT, "prop", NULL, NULL, 0);
792 3 : gf_props_parse_value(GF_PROP_LSINT, "prop", NULL, NULL, 0);
793 3 : gf_props_parse_value(GF_PROP_LUINT, "prop", NULL, NULL, 0);
794 3 : gf_props_parse_value(GF_PROP_FLOAT, "prop", NULL, NULL, 0);
795 3 : gf_props_parse_value(GF_PROP_DOUBLE, "prop", NULL, NULL, 0);
796 3 : gf_props_parse_value(GF_PROP_FRACTION, "prop", NULL, NULL, 0);
797 3 : gf_props_parse_value(GF_PROP_FRACTION64, "prop", NULL, NULL, 0);
798 3 : gf_props_parse_value(GF_PROP_VEC2I, "prop", NULL, NULL, 0);
799 3 : gf_props_parse_value(GF_PROP_VEC2, "prop", NULL, NULL, 0);
800 3 : gf_props_parse_value(GF_PROP_VEC3I, "prop", NULL, NULL, 0);
801 3 : gf_props_parse_value(GF_PROP_VEC4I, "prop", NULL, NULL, 0);
802 3 : gf_props_parse_value(GF_PROP_STRING, "prop", NULL, NULL, 0);
803 3 : gf_props_parse_value(GF_PROP_DATA, "prop", NULL, NULL, 0);
804 3 : gf_props_parse_value(GF_PROP_CONST_DATA, "prop", NULL, NULL, 0);
805 3 : gf_props_parse_value(GF_PROP_POINTER, "prop", NULL, NULL, 0);
806 3 : gf_props_parse_value(GF_PROP_UINT, "prop", "test", "foo|bar", 0);
807 3 : gf_props_parse_value(100, "prop", "test", NULL, 0);
808 :
809 : memset(&p, 0, sizeof(GF_PropertyValue));
810 3 : p2=p;
811 138 : for (i=GF_PROP_FORBIDEN; i<GF_PROP_LAST_DEFINED; i++) {
812 : char dump[GF_PROP_DUMP_ARG_SIZE];
813 135 : gf_props_get_type_name(i);
814 135 : p.type = p2.type = i;
815 135 : gf_props_equal(&p, &p2);
816 135 : gf_props_dump_val(&p, dump, GF_PROP_DUMP_DATA_NONE, NULL);
817 : }
818 3 : p.type = GF_PROP_DATA;
819 3 : p.value.data.size = 4;
820 3 : p.value.data.ptr = "test";
821 3 : p2 = p;
822 3 : p2.value.data.ptr = NULL;
823 3 : gf_props_equal(&p, &p2);
824 3 : p2.value.data.size = 3;
825 3 : p2.value.data.ptr = "test";
826 3 : gf_props_equal(&p, &p2);
827 3 : p2.value.data.size = 4;
828 3 : gf_props_equal(&p, &p2);
829 :
830 3 : p.type = GF_PROP_UINT_LIST;
831 3 : i=0;
832 3 : p.value.uint_list.nb_items=1;
833 3 : p.value.uint_list.vals = &i;
834 3 : p2 = p;
835 3 : gf_props_equal(&p, &p2);
836 :
837 :
838 3 : gf_log_set_strict_error(old_strict);
839 : }
840 :
841 385 : if (! strcmp( "UTSink", gf_filter_get_name(filter))) {
842 176 : stack->mode=UTF_MODE_SINK;
843 176 : gf_filter_set_max_extra_input_pids(filter, 10);
844 : }
845 209 : else if (! strcmp( "UTFilter", gf_filter_get_name(filter))) stack->mode=UTF_MODE_FILTER;
846 : else {
847 141 : stack->mode=UTF_MODE_SOURCE;
848 141 : return ut_filter_config_source(filter);
849 : }
850 : return GF_OK;
851 : }
852 :
853 : #define OFFS(_n) #_n, offsetof(GF_UnitTestFilter, _n)
854 : static const GF_FilterArgs UTFilterArgs[] =
855 : {
856 : { OFFS(pid_att), "set default value for PID `cust` attribute", GF_PROP_NAME, "UTSourceData", NULL, 0},
857 : { OFFS(max_pck), "maximum number of packets to send in source mode", GF_PROP_UINT, "1000", NULL, 0},
858 : { OFFS(nb_pids), "number of PIDs in source mode", GF_PROP_UINT, "1", "1-+I", 0},
859 : { OFFS(max_out), "maximum number of shared packets not yet released in source/filter mode, no limit if -1", GF_PROP_SINT, "-1", NULL, GF_FS_ARG_UPDATE},
860 : { OFFS(alloc), "use allocated memory packets in source mode", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_UPDATE},
861 : { OFFS(fwd), "indicate packet forward mode for filter.\n"
862 : "- shared: use shared memory (dangerous)\n"
863 : "- copy: use copy\n"
864 : "- ref: use references to source packet\n"
865 : "- mix: change mode at each packet sent", GF_PROP_UINT, "shared", "shared|copy|ref|mix", GF_FS_ARG_UPDATE},
866 : { OFFS(framing), "packet framing.\n"
867 : "- none: disable packet split\n"
868 : "- default: divide packets in 3 for filter mode and allows partial blocks for sink mode\n"
869 : "- nostart: same as default but does not signal packet start flag\n"
870 : "- noend: same as default but does not signal packet end flag"
871 : "", GF_PROP_UINT, "none", "none|default|nostart|noend", GF_FS_ARG_UPDATE},
872 : { OFFS(update), "send update message after half packet send. Update format is FID,argname,argval", GF_PROP_STRING, NULL, NULL, GF_FS_ARG_UPDATE},
873 : { OFFS(cov), "dump options and exercise error cases for code coverage", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_UPDATE},
874 : { OFFS(norecfg), "disable reconfig on input pid in filter/sink mode", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_UPDATE},
875 : { OFFS(gsftest), "dispatch a fake single video pid with props and packet props for GSF testing", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_UPDATE},
876 :
877 : { OFFS(dummy1), "dummy for coverage", GF_PROP_LSINT, "0", NULL, GF_FS_ARG_UPDATE},
878 : { OFFS(dummy1), "dummy for coverage", GF_PROP_LUINT, "0", NULL, GF_FS_ARG_UPDATE},
879 : { OFFS(dummy1), "dummy for coverage", GF_PROP_FLOAT, "0", NULL, GF_FS_ARG_UPDATE},
880 : { OFFS(dummy1), "dummy for coverage", GF_PROP_DOUBLE, "0", NULL, GF_FS_ARG_UPDATE},
881 : { OFFS(dummy1), "dummy for coverage", GF_PROP_FRACTION, "0", NULL, GF_FS_ARG_UPDATE},
882 : { OFFS(dummy1), "dummy for coverage", GF_PROP_POINTER, "0", NULL, GF_FS_ARG_UPDATE},
883 : { OFFS(dummy1), "dummy for coverage", GF_PROP_FRACTION64, "0", NULL, GF_FS_ARG_UPDATE},
884 : { NULL }
885 : };
886 :
887 : #define UT_CAP_CODE GF_4CC('c','u','s','t')
888 : static const GF_FilterCapability UTFilterCaps[] =
889 : {
890 : CAP_STRING(GF_CAPS_INPUT, UT_CAP_CODE, "UTSourceData"),
891 : CAP_STRING(GF_CAPS_INPUT, UT_CAP_CODE, "UTFilterData"),
892 : CAP_STRING(GF_CAPS_OUTPUT, UT_CAP_CODE, "UTSourceData"),
893 : CAP_STRING(GF_CAPS_OUTPUT, UT_CAP_CODE, "UTFilterData"),
894 : };
895 :
896 : static const GF_FilterCapability UTSinkInputs[] =
897 : {
898 : CAP_STRING(GF_CAPS_INPUT, UT_CAP_CODE, "UTSourceData"),
899 : };
900 :
901 : static const GF_FilterCapability UTSink2Inputs[] =
902 : {
903 : CAP_STRING(GF_CAPS_INPUT, UT_CAP_CODE, "UTFilterData"),
904 : };
905 :
906 : static const GF_FilterCapability UTSourceOutputs[] =
907 : {
908 : CAP_STRING(GF_CAPS_OUTPUT, UT_CAP_CODE, "UTSourceData"),
909 : };
910 :
911 :
912 : const GF_FilterRegister UTFilterRegister = {
913 : .name = "UTFilter",
914 : GF_FS_SET_DESCRIPTION("Unit Test Filter")
915 : GF_FS_SET_HELP("This filter is only used for unit testing of filter framework")
916 : .private_size = sizeof(GF_UnitTestFilter),
917 : .flags = GF_FS_REG_EXPLICIT_ONLY,
918 : SETCAPS( UTFilterCaps),
919 : .args = UTFilterArgs,
920 : .initialize = utfilter_initialize,
921 : .finalize = ut_filter_finalize,
922 : .process = ut_filter_process_filter,
923 : .configure_pid = ut_filter_config_input,
924 : .update_arg = ut_filter_update_arg
925 : };
926 :
927 :
928 : const GF_FilterRegister UTSinkRegister = {
929 : .name = "UTSink",
930 : GF_FS_SET_DESCRIPTION("Unit Test Sink")
931 : GF_FS_SET_HELP("This filter is only used for unit testing of filter framework")
932 : .private_size = sizeof(GF_UnitTestFilter),
933 : .flags = GF_FS_REG_EXPLICIT_ONLY,
934 : SETCAPS(UTSinkInputs),
935 : .args = UTFilterArgs,
936 : .initialize = utfilter_initialize,
937 : .finalize = ut_filter_finalize,
938 : .process = ut_filter_process_sink,
939 : .configure_pid = ut_filter_config_input,
940 : .update_arg = ut_filter_update_arg
941 : };
942 :
943 : const GF_FilterRegister UTSink2Register = {
944 : .name = "UTSink2",
945 : GF_FS_SET_DESCRIPTION("Unit Test Sink2")
946 : GF_FS_SET_HELP("This filter is only used for unit testing of filter framework")
947 : .private_size = sizeof(GF_UnitTestFilter),
948 : .flags = GF_FS_REG_EXPLICIT_ONLY,
949 : SETCAPS(UTSink2Inputs),
950 : .args = UTFilterArgs,
951 : .initialize = utfilter_initialize,
952 : .finalize = ut_filter_finalize,
953 : .process = ut_filter_process_sink,
954 : .configure_pid = ut_filter_config_input,
955 : .update_arg = ut_filter_update_arg
956 : };
957 :
958 : const GF_FilterRegister UTSourceRegister = {
959 : .name = "UTSource",
960 : GF_FS_SET_DESCRIPTION("Unit Test Source")
961 : GF_FS_SET_HELP("This filter is only used for unit testing of filter framework")
962 : .private_size = sizeof(GF_UnitTestFilter),
963 : .flags = GF_FS_REG_EXPLICIT_ONLY,
964 : SETCAPS(UTSourceOutputs),
965 : .args = UTFilterArgs,
966 : .initialize = utfilter_initialize,
967 : .finalize = ut_filter_finalize,
968 : .process = ut_filter_process_source,
969 : .update_arg = ut_filter_update_arg
970 : };
971 :
972 :
973 142 : const GF_FilterRegister *ut_filter_register(GF_FilterSession *session, Bool load_meta_filters)
974 : {
975 142 : return &UTFilterRegister;
976 : }
977 142 : const GF_FilterRegister *ut_source_register(GF_FilterSession *session, Bool load_meta_filters)
978 : {
979 142 : return &UTSourceRegister;
980 : }
981 142 : const GF_FilterRegister *ut_sink_register(GF_FilterSession *session, Bool load_meta_filters)
982 : {
983 142 : return &UTSinkRegister;
984 : }
985 142 : const GF_FilterRegister *ut_sink2_register(GF_FilterSession *session, Bool load_meta_filters)
986 : {
987 142 : return &UTSink2Register;
988 : }
989 :
990 :
991 :
|