1 /*
2  *  tcpvmexportd.c
3  *
4  *  Copyright (C) Marzio Malanchini - July 2003
5  *
6  *  This file is part of transcode, a video stream processing tool
7  *
8  *  transcode is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2, or (at your option)
11  *  any later version.
12  *
13  *  transcode is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with GNU Make; see the file COPYING.  If not, write to
20  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21  *
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27 
28 #include <unistd.h>
29 #include <stdlib.h>
30 #include <string.h>
31 
32 
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36 
37 #include "pvm_interface.h"
38 #include "pvm_parser.h"
39 
40 #include "transcode.h"
41 #include "export_pvm_slave.h"
42 #include "external_codec.h"
43 
44 #define EXE "tcpvmexportd"
45 
46 #define MAX_BUF 	1024
47 
48 #define MASTER_MODE	0x00000001
49 #define SLAVE_MODE	0x00000010
50 #define MERGER_MODE	0x00000100
51 #define CHECK_MODE	0x00001000
52 #define MAST_MERGE_MODE	MASTER_MODE|MERGER_MODE
53 #define MAST_CHECK_MODE	MASTER_MODE|CHECK_MODE
54 #define SLAVE_MERGE_MODE	SLAVE_MODE|MERGER_MODE
55 
56 
57 void *f_handle=NULL;	/*handle for dlopen/dlclose*/
58 void *f_ext_handle=NULL;	/*handle for dlopen/dlclose of the external module*/
59 #define tc_export p_tc_export
60 int (*tc_export)(int,void *,void *);
61 char *p_param1=NULL,*p_param2=NULL,*p_param3=NULL; /*codec input parameter*/
62 int tc_accel=-1;
63 int s_elab_type=TC_VIDEO,s_list_only=0;
64 char *p_out_file_name=NULL;
65 char *p_request_func=NULL;
66 char *p_hostname=NULL;
67 int verbose=TC_QUIET;
68 char *p_merge_cmd=NULL;
69 unsigned int tc_avi_limit=AVI_FILE_LIMIT;	/*NEED TO CHECK*/
70 int s_divxmultipass=0,s_internal_multipass=0;
71 
version()72 void version()
73 {
74   /* id string */
75   fprintf(stderr, "%s (%s v%s) (C) 2001-2003 Thomas Oestreich\n",
76 	  EXE, PACKAGE, VERSION);
77 }
78 
79 
usage(int status)80 static void usage(int status)
81 {
82 	version();
83 	fprintf(stderr,"\nUsage: %s -s|-m [options]\n", EXE);
84 	fprintf(stderr,"\t -s             start %s in slave mode [default]\n",EXE);
85 	fprintf(stderr,"\t -m             start %s in master mode [off]\n",EXE);
86 	fprintf(stderr,"\t -j             start %s in merge mode [off]\n",EXE);
87 	fprintf(stderr,"\t -L             create only the merge list [off]\n");
88 	fprintf(stderr,"\t -p number      Multipass. [0]\n");
89 	fprintf(stderr,"\t -C             Check the config or merge file [off]\n");
90 	fprintf(stderr,"\t -M             Enable internal multipass [off]\n");
91 	fprintf(stderr,"\t -c name        name of slave function req in slave mode [none]\n");
92 	fprintf(stderr,"\t -x parameters  multiplex parameters [none]\n");
93 	fprintf(stderr,"\t -t type        elab video or audio frame (video|audio|system|multisystem) [video]\n");
94 	fprintf(stderr,"\t -f name        out file name [/tmp/my_file_name]\n");
95 	fprintf(stderr,"\t -1 param       first parameter to pass to the slave function [null]\n");
96 	fprintf(stderr,"\t -2 param       second parameter to pass to the slave function [null]\n");
97 	fprintf(stderr,"\t -3 param       third parameter to pass to the slave function [null]\n");
98 	fprintf(stderr,"\t -d level       verbose level 0|1|2 [0]\n");
99 	fprintf(stderr,"\t -h             print this help\n");
100 	fprintf(stderr,"\t -v             print version\n");
101 	exit(status);
102 }
103 
104 
f_init_func(char * p_option,char * p_mod)105 int f_init_func(char *p_option,char *p_mod)
106 {
107 	const char *p_error;
108 	char *p_modpath=MOD_PATH;
109 	char s_module[MAX_BUF];
110 
111 	if(!strcasecmp(p_option,"open-external"))
112 	{
113 		if (p_mod!=NULL)
114 		{
115 			memset(s_module,'\0',sizeof(s_module));
116 			tc_snprintf(s_module, sizeof(s_module), "%s/export_%s.so", p_modpath,p_mod);
117 			f_ext_handle=dlopen(s_module, RTLD_GLOBAL|RTLD_LAZY);
118 			if (!f_ext_handle)
119 			{
120 				fputs (dlerror(), stderr);
121 				dlclose(f_handle);
122 				return(1);
123 			}
124 			tc_export = dlsym(f_ext_handle, "tc_export");
125 			if ((p_error = dlerror()) != NULL)
126 			{
127 				fputs(p_error, stderr);
128 				return(1);
129 			}
130 		}
131 	}
132 	else if(!strcasecmp(p_option,"close-external"))
133 	{
134 		if (f_ext_handle!=NULL)
135 			dlclose(f_ext_handle);
136 		f_ext_handle=NULL;
137 		tc_export=NULL;
138 	}
139 	else if(!strcasecmp(p_option,"status-external"))
140 	{
141 		if(f_ext_handle!=NULL)
142 			return(1);
143 	}
144 	else if(!strcasecmp(p_option,"open"))
145 	{
146 		if (p_mod!=NULL)
147 		{
148 			tc_accel = ac_cpuinfo();
149 			memset(s_module,'\0',sizeof(s_module));
150 			tc_snprintf(s_module, sizeof(s_module), "%s/export_%s.so", p_modpath,p_mod);
151 			f_ext_handle=dlopen(s_module, RTLD_GLOBAL|RTLD_LAZY);
152 			if (!f_ext_handle)
153 			{
154 				fputs (dlerror(), stderr);
155 				dlclose(f_handle);
156 				return(1);
157 			}
158 			tc_export = dlsym(f_ext_handle, "tc_export");
159 			if ((p_error = dlerror()) != NULL)
160 			{
161 				fputs(p_error, stderr);
162 				return(1);
163 			}
164 		}
165 		if ((f_handle=f_init_pvm_func("open",NULL))==NULL)
166 			return(1);
167 	}
168 	else if(!strcasecmp(p_option,"close"))
169 	{
170 		if (f_ext_handle!=NULL)
171 			dlclose(f_ext_handle);
172 		(void *)f_init_pvm_func("close",f_handle);
173 		f_ext_handle=NULL;
174 		f_handle=NULL;
175 	}
176 	else
177 	{
178 		fprintf(stderr,"(%s) invalid command \"%s\"\n",__FILE__,p_option);
179 		return(1);
180 	}
181 	return(0);
182 }
183 
184 
185 
main(int argc,char ** argv)186 int main(int argc,char **argv)
187 {
188 	char s_cmd;
189 	char *p_argv[]={"-s",(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0};
190 	int s_slave=0,s_cont=1,s_file_dest;
191 	char *p_tmp_file="/tmp/my_file_name";
192 	pvm_config_env *p_pvm_conf;
193 	pvm_config_filelist *p_my_filelist=NULL;
194 	char s_hostname[MAX_BUF];
195 
196 	p_out_file_name=p_tmp_file;
197 
198 	if((gethostname(s_hostname,sizeof(s_hostname)))!=0)
199 	{
200 		memset(s_hostname,'\0',sizeof(s_hostname));
201 		tc_snprintf(s_hostname,sizeof(s_hostname),"localhost-%d\n",getpid());
202 	}
203 	p_hostname=(char *)s_hostname;
204 
205 	while ((s_cmd = getopt(argc, argv, "mMCLsjx:c:1:2:3:t:f:d:p:vh")) != -1)
206 	{
207 		switch (s_cmd)
208 		{
209 			case 'c':
210 		  		if(optarg[0]=='-')
211 			  		usage(EXIT_FAILURE);
212 		  		p_argv[s_cont++]="-c";
213 		  		p_argv[s_cont++]=p_request_func=optarg;
214 		  	break;
215 			case 'M':
216 				s_internal_multipass=1;
217 		  	break;
218 			case 'p':
219 				s_divxmultipass=((atoi(optarg)<0)||(atoi(optarg)>3))?0:atoi(optarg);
220 		  	break;
221 			case 'd':
222 				verbose=((atoi(optarg)<0)||(atoi(optarg)>2))?0:atoi(optarg);
223 		  	break;
224 			case 'C':
225 		  		s_slave|=CHECK_MODE;
226 		  	break;
227 			case 'L':
228 		  		s_list_only=1;
229 		  	break;
230 			case 'j':
231 		  		s_slave|=MERGER_MODE;
232 		  	break;
233 			case 's':
234 		  		s_slave|=SLAVE_MODE;		/*default*/
235 		  	break;
236 			case 'm':
237 		  		s_slave|=MASTER_MODE;
238 		  	break;
239 			case 'f':
240 		  		p_argv[s_cont++]="-f";
241 		  		p_argv[s_cont++]=p_out_file_name=optarg;
242 		  	break;
243 			case 't':
244 		  		p_argv[s_cont++]="-t";
245 		  		p_argv[s_cont++]=optarg;
246 				if(!strcasecmp(optarg,"video"))
247 					s_elab_type=TC_VIDEO;
248 				else if(!strcasecmp(optarg,"audio"))
249 					s_elab_type=TC_AUDIO;
250 				else if(!strcasecmp(optarg,"system"))
251 					s_elab_type=TC_VIDEO_AUDIO;
252 				else if(!strcasecmp(optarg,"multisystem"))
253 					s_elab_type=TC_MULTI_VIDEO_AUDIO;
254 				else
255 					usage(EXIT_FAILURE);
256 		  	break;
257 			case 'x':
258 		  		p_merge_cmd=optarg;	/*multiplex command*/
259 		  	break;
260 			case '1':
261 		  		p_param1=strtok(optarg,"\"");	/*First parameter*/
262 		  	break;
263 			case '2':
264 		  		p_param2=strtok(optarg,"\"");	/*Second parameter*/
265 		  	break;
266 			case '3':
267 		  		p_param3=strtok(optarg,"\"");	/*Third parameter*/
268 		  	break;
269 			case 'v':
270 		  		version();
271 		  		exit(0);
272 		  	break;
273 			case 'h':
274 		  		usage(EXIT_SUCCESS);
275 			default:
276 				usage(EXIT_FAILURE);
277 		}
278 	}
279 
280 	if(optind < argc)
281 	{
282 		if(strcmp(argv[optind],"-")!=0)
283 			usage(EXIT_FAILURE);
284         }
285 	if(argc==1)
286 		usage(EXIT_FAILURE);
287 	if (((s_slave==SLAVE_MODE)||(s_slave==(SLAVE_MERGE_MODE)))&&(p_request_func==NULL))
288 		usage(EXIT_FAILURE);
289 	if ((s_slave==(MAST_MERGE_MODE)||s_slave==(MAST_CHECK_MODE))&&(p_out_file_name==NULL))
290 		usage(EXIT_FAILURE);
291 	switch(s_slave)
292 	{
293 		case MAST_CHECK_MODE:
294 		case MAST_MERGE_MODE:
295 			p_pvm_conf = pvm_parser_open(p_out_file_name,verbose, 1);
296 			if (p_pvm_conf == NULL)
297 			{
298 				fprintf(stderr,"[%s] error checking %s\n",EXE,p_out_file_name);
299 				exit(1);
300 			}
301 			if (s_slave == (MAST_MERGE_MODE))
302 			{
303 				if (p_pvm_conf->s_sys_list.p_destination!=NULL)	/*syslist?*/
304 				{
305 					if(f_system_merge(p_pvm_conf))	/*if 1 then error*/
306 						exit(1);
307 				}
308 				else if (p_pvm_conf->p_add_list->p_destination!=NULL)
309 				{
310 					if ((s_file_dest=creat(p_pvm_conf->p_add_list->p_destination,S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH))==-1)
311 					{
312 						fprintf(stderr,"[%s] can't create %s output file.\n",EXE,p_pvm_conf->p_add_list->p_destination);
313 						pvm_parser_close();
314                         p_pvm_conf=NULL;
315 						exit(1);
316 					}
317 					for (p_my_filelist=p_pvm_conf->p_add_list;p_my_filelist!=NULL;p_my_filelist=p_my_filelist->p_next)
318 					{
319 						fprintf(stderr,"[%s] merge into %s and remove file %s\n",EXE,p_pvm_conf->p_add_list->p_destination,p_my_filelist->p_filename);
320 						if(f_copy_remove_func("open",p_my_filelist->p_filename,s_file_dest))	/*if 1 then error*/
321 							exit(1);
322 					}
323 					close(s_file_dest);
324 					f_copy_remove_func("close",NULL,0);
325 				}
326 				else
327 				{
328 					fprintf(stderr,"[%s] no destination file name.\n",EXE);
329 					exit(1);
330 				}
331 				for (p_my_filelist=p_pvm_conf->p_rem_list;p_my_filelist!=NULL;p_my_filelist=p_my_filelist->p_next)
332 				{
333 					fprintf(stderr,"[%s] remove file %s\n",EXE,p_my_filelist->p_filename);
334 					remove(p_my_filelist->p_filename);
335 				}
336 			}
337 			pvm_parser_close();
338 			p_pvm_conf=NULL;
339 		break;
340 		case SLAVE_MODE:
341 		case SLAVE_MERGE_MODE:
342 			if((!strcasecmp(p_request_func,"mpeg2enc-mp2enc"))||(!strcasecmp(p_request_func,"mpeg-mpeg"))||(!strcasecmp(p_request_func,"avi-avi")))
343 			{
344 				if (f_init_func("open",NULL))		/*init the pvm interface*/
345 					exit(1);
346 				f_pvm_skeduler(f_export_func);
347 			}
348 			else
349 			{
350 				if (f_init_func("open",p_request_func))
351 					exit(1);
352 				f_pvm_skeduler(f_export_func);
353 			}
354 		break;
355 		default:
356 		break;
357 	}
358 	f_init_func("close",NULL);
359 	return(0);
360 }
361