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