1 /*
2  * Copyright (C) 2004 Nathan Lutchansky <lutchann@litech.org>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program 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
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  */
18 
19 #include <sys/types.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <unistd.h>
23 #include <string.h>
24 #include <pthread.h>
25 
26 #include <event.h>
27 #include <log.h>
28 #include <frame.h>
29 #include <stream.h>
30 #include <filters.h>
31 #include <conf_parse.h>
32 
33 struct framedropper {
34 	struct stream *output;
35 	struct stream_destination *input;
36 	int scale;
37 	int count;
38 };
39 
do_framedrop(struct frame * input,void * d)40 static void do_framedrop( struct frame *input, void *d )
41 {
42 	struct framedropper *drop = (struct framedropper *)d;
43 
44 	if( drop->count == 0 ) deliver_frame_to_stream( input, drop->output );
45 	else unref_frame( input );
46 
47 	if( ++drop->count == drop->scale ) drop->count = 0;
48 }
49 
get_framerate(struct stream * s,int * fincr,int * fbase)50 static void get_framerate( struct stream *s, int *fincr, int *fbase )
51 {
52 	struct framedropper *drop = (struct framedropper *)s->private;
53 
54 	drop->input->stream->get_framerate( drop->input->stream, fincr, fbase );
55 	*fincr *= drop->scale;
56 }
57 
set_running(struct stream * s,int running)58 static void set_running( struct stream *s, int running )
59 {
60 	struct framedropper *drop = (struct framedropper *)s->private;
61 
62 	set_waiting( drop->input, running );
63 }
64 
65 /************************ CONFIGURATION DIRECTIVES ************************/
66 
start_block(void)67 static void *start_block(void)
68 {
69 	struct framedropper *drop;
70 
71 	drop = (struct framedropper *)malloc( sizeof( struct framedropper ) );
72 	drop->output = 0;
73 	drop->scale = 0;
74 	drop->count = 0;
75 
76 	return drop;
77 }
78 
end_block(void * d)79 static int end_block( void *d )
80 {
81 	struct framedropper *drop = (struct framedropper *)d;
82 
83 	if( ! drop->input )
84 	{
85 		spook_log( SL_ERR,
86 			"framedrop: missing input stream name" );
87 		return -1;
88 	}
89 	if( ! drop->output )
90 	{
91 		spook_log( SL_ERR,
92 			"framedrop: missing output stream name" );
93 		return -1;
94 	}
95 	if( drop->scale < 1 )
96 	{
97 		spook_log( SL_ERR,
98 			"framedrop: missing scale factor" );
99 		return -1;
100 	}
101 
102 	return 0;
103 }
104 
set_input(int num_tokens,struct token * tokens,void * d)105 static int set_input( int num_tokens, struct token *tokens, void *d )
106 {
107 	struct framedropper *drop = (struct framedropper *)d;
108 
109 	if( ! ( drop->input = connect_to_stream( tokens[1].v.str, do_framedrop,
110 						drop, NULL, 0 ) ) )
111 	{
112 		spook_log( SL_ERR,
113 			"framedrop: unable to connect to stream \"%s\"\n",
114 				tokens[1].v.str );
115 		return -1;
116 	}
117 	return 0;
118 }
119 
set_output(int num_tokens,struct token * tokens,void * d)120 static int set_output( int num_tokens, struct token *tokens, void *d )
121 {
122 	struct framedropper *drop = (struct framedropper *)d;
123 
124 	if( ! drop->input )
125 	{
126 		spook_log( SL_ERR,
127 			"framedrop: input must be specified before output" );
128 		return -1;
129 	}
130 	drop->output = new_stream( tokens[1].v.str,
131 					drop->input->stream->format, drop );
132 	if( ! drop->output )
133 	{
134 		spook_log( SL_ERR,
135 			"framedrop: unable to create stream \"%s\"",
136 			tokens[1].v.str );
137 		return -1;
138 	}
139 	drop->output->get_framerate = get_framerate;
140 	drop->output->set_running = set_running;
141 	return 0;
142 }
143 
set_scale(int num_tokens,struct token * tokens,void * d)144 static int set_scale( int num_tokens, struct token *tokens, void *d )
145 {
146 	struct framedropper *drop = (struct framedropper *)d;
147 
148 	if( tokens[1].v.num < 1 )
149 	{
150 		spook_log( SL_ERR,
151 			"framedrop: scale factor cannot be less than 1!" );
152 		return -1;
153 	}
154 	drop->scale = tokens[1].v.num;
155 	return 0;
156 }
157 
158 static struct statement config_statements[] = {
159 	/* directive name, process function, min args, max args, arg types */
160 	{ "input", set_input, 1, 1, { TOKEN_STR } },
161 	{ "output", set_output, 1, 1, { TOKEN_STR } },
162 	{ "scale", set_scale, 1, 1, { TOKEN_NUM } },
163 
164 	/* empty terminator -- do not remove */
165 	{ NULL, NULL, 0, 0, {} }
166 };
167 
framedrop_init(void)168 int framedrop_init(void)
169 {
170 	register_config_context( "filter", "framedrop", start_block, end_block,
171 					config_statements );
172 	return 0;
173 }
174