1 /*
2  *  export_pvm.c
3  *
4  *  Copyright (C) Malanchini Marzio - June 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 #include "transcode.h"
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 
29 #include "pvm_version.h"
30 #include "pvm_interface.h"
31 #include "pvm_parser.h"
32 #include "external_codec.h"
33 #include "vob_pack_unpack.h"
34 
35 #define MOD_NAME    "export_pvm.so"
36 #define MOD_VERSION  EXPORT_PVM_VERSION
37 #define MOD_CODEC   "(video) * | (audio) *"
38 
39 #define MAX_BUF 1024
40 
41 #define MIN_TOT_NPROC   1
42 #define MIN_FRAME   10
43 
44 static int verbose_flag=TC_QUIET;
45 static int capability_flag=-1; //all codecs are welcome
46 
47 #define MOD_PRE pvm
48 #include "export_def.h"
49 
50 static int s_merger_tid_audio[]={-1,-1},s_merger_tid_video[]={-1,-1},s_init_check=0;
51 static int s_merger_tid_system[]={-1,-1};
52 static int s_null_video_module=0,s_null_audio_module=0,s_sys_merger_started=-1;
53 static void *p_handle=NULL;
54 static pvm_func_t s_pvm_single_proc_audio,s_pvm_single_proc_video,s_pvm_fun_audio,s_pvm_fun_video,s_pvm_single_proc_system;
55 static pvm_config_env s_pvm_conf,*p_pvm_conf=NULL;
56 
57 static char *p_par1=NULL,*p_par2=NULL;
58 
59 
60 extern pthread_mutex_t s_channel_lock;
61 
adjust_ch(char * line,char ch)62 static void adjust_ch(char *line, char ch)
63 {
64   char *src = &line[strlen(line)];
65   char *dst = line;
66 
67   //-- remove blanks from right and left side --
68   do { src--; } while ( (src != line) && (*src == ch) );
69   *(src+1) = '\0';
70   src = line;
71   while (*src == ch) src++;
72 
73   if (src == line) return;
74 
75   //-- copy rest --
76   while (*src)
77   {
78     *dst = *src;
79     src++;
80     dst++;
81   }
82   *dst = '\0';
83 }
84 
f_pvm_balancer(char * p_option,pvm_func_t * p_func,int s_seq,int s_type)85 static void f_pvm_balancer(char *p_option,pvm_func_t *p_func,int s_seq,int s_type)
86 {
87     int s_cont,s_dummy,s_dummy1,s_rc;
88 
89     if (!strcasecmp(p_option, "open"))
90     {
91         for(s_cont=0;s_cont<p_func->s_nproc;s_cont++)
92             p_func->p_used_tid[s_cont]=INT_MAX; /*setup to INT_MAX*/
93         p_func->s_current_tid=0;    /*First tid*/
94     }
95     else if (!strcasecmp(p_option, "close"))
96     {
97         for(s_cont=0;s_cont<p_func->s_nproc;s_cont++)
98             p_func->p_used_tid[s_cont]=INT_MAX; /*setup to INT_MAX*/
99     }
100     else if (!strcasecmp(p_option, "set-seq"))
101     {
102         p_func->p_used_tid[p_func->s_current_tid]=s_seq;
103     }
104     else if (!strcasecmp(p_option, "first-free"))
105     {
106         for(s_cont=(((1+p_func->s_current_tid)==p_func->s_nproc)?0:(1+p_func->s_current_tid));((p_func->p_used_tid[s_cont]!=INT_MAX)&&(s_cont<p_func->s_current_tid));s_cont=((((1+s_cont)==p_func->s_nproc)?0:(1+s_cont))));   /*det the first task free*/
107 //      for(s_cont=0;((p_func->p_used_tid[s_cont]!=INT_MAX)&&(s_cont<p_func->s_nproc));s_cont++);   /*det the first task free*/
108         if ((s_cont<p_func->s_nproc)&&(p_func->p_used_tid[s_cont]==INT_MAX))    /*it's already assigned to a running task?*/
109         {
110             p_func->s_current_tid=s_cont;   /*setting up the new task*/
111             if (verbose_flag & TC_DEBUG)
112             {
113                 if (s_type== TC_VIDEO)
114                     tc_log_info(MOD_NAME, "The new task for video is %d",s_cont);
115                 else
116                     tc_log_info(MOD_NAME, "The new task for audio is %d",s_cont);
117             }
118         }
119         else    /*stop and wait for the first free task*/
120         {
121             if (verbose_flag & TC_DEBUG)
122             {
123                 if (s_type== TC_VIDEO)
124                     tc_log_info(MOD_NAME, "Waiting for a video free task...");
125                 else
126                     tc_log_info(MOD_NAME, "Waiting for an audio free task...");
127             }
128             s_cont=s_seq;
129             if (s_type== TC_VIDEO)
130                 (int)f_pvm_set_recv(PVM_MSG_ENDTASK_VIDEO); /*set up to receive the PVM_MSG_ENDTASK_VIDEO*/
131             else
132                 (int)f_pvm_set_recv(PVM_MSG_ENDTASK_AUDIO); /*set up to receive the PVM_MSG_ENDTASK_AUDIO*/
133             s_seq=f_pvm_recv(&s_dummy,(char *)&s_dummy1,&s_rc); /*Waiting for a free task */
134             (int)f_pvm_set_recv(s_cont);    /*set up to receive the prev seq*/
135             for(s_cont=0;p_func->p_used_tid[s_cont]!=s_seq;s_cont++);   /*det the task free*/
136             p_func->s_current_tid=s_cont;   /*setting up the new task*/
137             if (verbose_flag & TC_DEBUG)
138             {
139                 if (s_type== TC_VIDEO)
140                     tc_log_info(MOD_NAME, "The new video task free is %d",s_cont);
141                 else
142                     tc_log_info(MOD_NAME, "The new audio task free is %d",s_cont);
143             }
144         }
145     }
146 }
147 
f_help(void)148 static void f_help(void)
149 {
150     tc_log_info(MOD_NAME, "%s",MOD_VERSION);
151     tc_log_info(MOD_NAME, "  -F configfile,[[nproc]:[maxproc]:[nfrxtask]]");
152     tc_log_info(MOD_NAME, "  nproc,maxproc,nfrxtask override the parameter present in the config file");
153     tc_log_info(MOD_NAME, "  List of known and supported codecs:");
154     f_help_codec(MOD_NAME);
155 }
156 
157 #define PVM_DEINIT do { \
158     if (s_init_check == 1) { \
159         void *ret = f_init_pvm_func("close", p_handle); \
160         s_init_check = (ret != NULL) ?1 :0; /* uhm... -- Fromani */ \
161     } else { \
162         s_init_check -= 1; \
163     } \
164 } while (0)
165 
166 #define PVM_CLOSE do { \
167     f_pvm_balancer("close", p_pvm_fun, 0, param->flag); \
168     f_pvm_master_start_stop("close", "tcpvmexportd", NULL, \
169                             p_pvm_conf->s_nproc, p_pvm_conf->s_max_proc, p_pvm_fun); \
170     PVM_DEINIT; \
171 } while (0)
172 
173 /* ------------------------------------------------------------
174  *
175  * open codec
176  *
177  * ------------------------------------------------------------*/
178 
179 MOD_open
180 {
181     pvm_func_t *p_pvm_fun=NULL;
182     int s_null_module;
183 
184     pthread_mutex_lock(&s_channel_lock);    /*this is the only way to make my module work with nultithreads: need to change all the code*/
185     if(param->flag == TC_VIDEO)
186     {
187         s_null_module=s_null_video_module;
188         p_pvm_fun=&s_pvm_fun_video;
189         if (verbose_flag & TC_DEBUG)
190             tc_log_info(MOD_NAME, "enter in MOD_OPEN Video");
191     }
192     else
193     {
194         s_null_module=s_null_audio_module;
195         p_pvm_fun=&s_pvm_fun_audio;
196         if (verbose_flag & TC_DEBUG)
197             tc_log_info(MOD_NAME, "enter in MOD_OPEN Video");
198     }
199     if (!s_null_module)
200     {
201         if((f_pvm_multi_send(0,(char *)0,PVM_EXP_OPT_OPEN,p_pvm_fun))==-1)
202         {
203             PVM_CLOSE;
204             pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
205             return TC_ERROR;
206         }
207     }
208     pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
209     if (verbose_flag & TC_DEBUG)
210         tc_log_info(MOD_NAME, "exit MOD_OPEN Video");
211     return TC_OK;
212 }
213 
214 /* ------------------------------------------------------------
215  *
216  * init codec
217  *
218  * ------------------------------------------------------------*/
219 
220 MOD_init
221 {
222     char *p_file_to_open=NULL;
223     char *p_tmp=NULL;
224     char *p_vob_buffer=NULL;
225     char *p_argv[]={"-s",(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0};
226     char *p_argv_merger[]={"-s","-j",(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0};
227     char *p_argv_merger_sys[]={"-s","-j",(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0,(char*)0};
228     int s_cont = 1, s_contj = 2, s_contsys = 2, s_vob_buffer_size;
229     pvm_config_codec    *p_conf_codec;
230     pvm_func_t *p_pvm_fun=NULL;
231     pvm_func_t *p_pvm_single_proc=NULL;
232     int *p_merger_tid,*p_merger_sys_tid=0;
233     int s_null_module=0;
234     pvm_config_merger *p_merger_conf=NULL;
235     char s_version[MAX_BUF];
236     static int s_msys=0;
237 
238     pthread_mutex_lock(&s_channel_lock);    /*this is the only way to make my module work with nultithreads: need to change all the code*/
239     if (verbose_flag & TC_DEBUG)
240         tc_log_info(MOD_NAME, "enter in MOD_INIT");
241     if (s_init_check==0)
242     {
243         s_init_check++;     //do it only for the first time
244         memset((char *)&s_pvm_conf,'\0',sizeof(pvm_config_env));
245         p_pvm_conf=&s_pvm_conf;
246         if(vob->ex_v_fcc != NULL && strlen(vob->ex_v_fcc) != 0)
247         {
248             p_par1 = tc_strdup(vob->ex_v_fcc); /* ...and memleaks for all! */
249             adjust_ch(p_par1, ' ');    /*-- module to recall --*/
250             if(!strcasecmp(p_par1,"list"))
251             {
252                 f_help();
253                 pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
254                 return TC_ERROR;
255             }
256             p_pvm_conf = pvm_parser_open(p_par1, verbose, 0);
257             if (p_pvm_conf == NULL)
258             {
259                 tc_log_warn(MOD_NAME, "error checking %s",p_par1);
260                 f_help();
261                 pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
262                 return TC_ERROR;
263             }
264             ac_memcpy((char *)&s_pvm_conf,(char *)p_pvm_conf,sizeof(pvm_config_env));
265             p_pvm_conf=&s_pvm_conf;
266         }
267         else    //need at least the config file
268         {
269             f_help();
270             pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
271             return TC_ERROR;
272         }
273         if(vob->ex_a_fcc != NULL && strlen(vob->ex_a_fcc) != 0)
274         {
275             p_par2 = tc_strdup(vob->ex_a_fcc);
276             adjust_ch(p_par2, ' '); /*-- first parameter of the module --*/
277             if (p_par2[0]==':')
278             {
279                 if (p_pvm_conf->s_nproc==0)
280                     p_pvm_conf->s_nproc=1;  /*default nproc per host*/
281                 if (p_par2[1]==':')
282                 {
283                     if (p_pvm_conf->s_max_proc==0)
284                         p_pvm_conf->s_max_proc=10;
285                 }
286                 else
287                 {
288                     p_tmp=strtok(p_par2,":");
289                     if (p_tmp==NULL)
290                     {
291                         if (p_pvm_conf->s_max_proc==0)
292                             p_pvm_conf->s_max_proc=10;
293                     }
294                     else
295                     {
296                         p_pvm_conf->s_max_proc=atoi(p_tmp);
297                         p_pvm_conf->s_max_proc=(p_pvm_conf->s_max_proc<MIN_TOT_NPROC)?10:p_pvm_conf->s_max_proc;    /*the max is set to 10*/
298                     }
299                 }
300                 p_tmp=strtok(NULL,":");
301                 if (p_tmp==NULL)
302                 {
303                     if (p_pvm_conf->s_num_frame_task==0)
304                         p_pvm_conf->s_num_frame_task=100;
305                 }
306                 else
307                 {
308                     p_pvm_conf->s_num_frame_task=atoi(p_tmp);
309                     p_pvm_conf->s_num_frame_task=(p_pvm_conf->s_num_frame_task<MIN_FRAME)?100:p_pvm_conf->s_num_frame_task; /*the to the default */
310                 }
311             }
312             else
313             {
314                 p_pvm_conf->s_nproc=atoi(strtok(p_par2,":"));
315                 p_pvm_conf->s_nproc=((p_pvm_conf->s_nproc)<1)?1:p_pvm_conf->s_nproc;    /*the min is set to 2*/
316                 p_tmp=strtok(NULL,":");
317                 if (p_tmp==NULL)
318                 {
319                     if (p_pvm_conf->s_max_proc==0)
320                         p_pvm_conf->s_max_proc=10;
321                 }
322                 else
323                 {
324                     p_pvm_conf->s_max_proc=atoi(p_tmp);
325                     p_pvm_conf->s_max_proc=(p_pvm_conf->s_max_proc<MIN_TOT_NPROC)?10:p_pvm_conf->s_max_proc;    /*the max is set to 10*/
326                 }
327                 p_tmp=strtok(NULL,":");
328                 if (p_tmp==NULL)
329                 {
330                     if (p_pvm_conf->s_num_frame_task==0)
331                         p_pvm_conf->s_num_frame_task=100;
332                 }
333                 else
334                 {
335                     p_pvm_conf->s_num_frame_task=atoi(p_tmp);
336                     p_pvm_conf->s_num_frame_task=(p_pvm_conf->s_num_frame_task<MIN_FRAME)?100:p_pvm_conf->s_num_frame_task;
337                 }
338             }
339         }
340     }
341     else
342     {
343         s_init_check++;
344     }
345     if(param->flag == TC_VIDEO)
346     {
347         p_conf_codec=&(p_pvm_conf->s_video_codec);
348         p_file_to_open = tc_strdup(vob->video_out_file);
349         p_merger_conf=&(p_pvm_conf->s_video_merger);
350     }
351     else
352     {
353         p_conf_codec=&(p_pvm_conf->s_audio_codec);
354         if (vob->audio_out_file !=NULL)
355             p_file_to_open = tc_strdup(vob->audio_out_file);
356         else
357             p_file_to_open = tc_strdup(vob->video_out_file);
358         p_merger_conf=&(p_pvm_conf->s_audio_merger);
359     }
360     if (p_pvm_conf->p_multiplex_cmd!=NULL)
361     {
362         p_argv_merger_sys[s_contsys++]="-x";
363         p_argv_merger_sys[s_contsys++]=p_pvm_conf->p_multiplex_cmd;
364     }
365     if (f_supported_export_module(p_conf_codec->p_codec))
366     {
367         p_argv[s_cont++]="-c";
368         p_argv[s_cont++]=p_conf_codec->p_codec; /*store the parameter*/
369         p_argv_merger[s_contj++]="-c";
370         p_argv_merger[s_contj++]=p_conf_codec->p_codec; /*store the parameter*/
371         p_argv_merger_sys[s_contsys++]="-c";
372         if ((p_argv_merger_sys[s_contsys++]=f_supported_system((pvm_config_codec *)&(p_pvm_conf->s_video_codec),(pvm_config_codec *)&(p_pvm_conf->s_audio_codec)))!=NULL)
373         {
374             if (p_pvm_conf->s_system_merger.p_hostname!=NULL)
375             {
376                 if (vob->divxmultipass!=1)
377                     s_sys_merger_started=0;
378                 else            /*if multipass == 1 i don't need to start the system merger*/
379                 {
380                     s_contsys--;
381                     p_argv_merger_sys[s_contsys]="unknown"; /*store the parameter*/
382                     s_sys_merger_started=-1;    /*so the system merger never started*/
383                 }
384             }
385             else
386             {
387                 s_contsys--;
388                 p_argv_merger_sys[s_contsys]="unknown"; /*store the parameter*/
389                 s_sys_merger_started=-1;    /*so the system merger never started*/
390             }
391         }
392         else
393         {
394             p_argv_merger_sys[s_contsys-1]="unknown"; /*store the parameter*/
395             s_sys_merger_started=-1;    /*so the system merger never started*/
396         }
397         if (p_conf_codec->p_par1!=NULL)
398             if (p_conf_codec->p_par1[0]!=' ')
399             {
400                 p_argv[s_cont++]="-1";
401                 p_argv[s_cont++]=p_conf_codec->p_par1; /*store the parameter*/
402                 p_argv_merger[s_contj++]="-1";
403                 p_argv_merger[s_contj++]=p_conf_codec->p_par1; /*store the parameter*/
404                 p_argv_merger_sys[s_contsys++]="-1";
405                 p_argv_merger_sys[s_contsys++]=p_conf_codec->p_par1; /*store the parameter*/
406             }
407         if (p_conf_codec->p_par2!=NULL)
408             if (p_conf_codec->p_par2[0]!=' ')
409             {
410                 p_argv[s_cont++]="-2";
411                 p_argv[s_cont++]=p_conf_codec->p_par2; /*store the parameter*/
412             }
413         if (p_conf_codec->p_par3!=NULL)
414             if (p_conf_codec->p_par3[0]!=' ')
415             {
416                 p_argv[s_cont++]="-3";
417                 p_argv[s_cont++]=p_conf_codec->p_par3; /*store the parameter*/
418             }
419     }
420     else if (!strcasecmp(p_conf_codec->p_codec, "null"))
421     {
422         s_null_module=1;
423         if(param->flag == TC_VIDEO)
424         {
425             s_null_video_module=s_null_module;
426             tc_log_info(MOD_NAME, "use internal video null codec");
427         }
428         else
429         {
430             s_null_audio_module=s_null_module;
431             tc_log_info(MOD_NAME, "use internal audio null codec");
432         }
433     }
434     else
435     {
436         tc_log_warn(MOD_NAME, "unsupported %s codec",p_conf_codec->p_codec);
437         f_help();       /*unsupported codec parameter*/
438         pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
439         return TC_ERROR;
440     }
441     if ((!strcasecmp(p_pvm_conf->s_audio_codec.p_codec, "null"))||(!strcasecmp(p_pvm_conf->s_video_codec.p_codec, "null")))
442     {
443         s_sys_merger_started=-1;    /*so the system merger never started*/
444         p_pvm_conf->s_system_merger.p_hostname=NULL;
445     }
446     if (!s_null_module) /*skip if null module is requested*/
447     {
448         /*check the default setup*/
449         p_pvm_conf->s_nproc=(p_pvm_conf->s_nproc<1)?1:p_pvm_conf->s_nproc;
450         p_pvm_conf->s_max_proc=(p_pvm_conf->s_max_proc<MIN_TOT_NPROC)?10:p_pvm_conf->s_max_proc;
451         p_pvm_conf->s_num_frame_task=(p_pvm_conf->s_num_frame_task<MIN_FRAME)?100:p_pvm_conf->s_num_frame_task;
452 
453         if ((vob->divxmultipass==0)&&(p_pvm_conf->s_internal_multipass))
454         {
455             p_argv[s_cont++]="-M";  /*use internale multipass only if -R option isn't set*/
456         }
457         else
458         {
459             p_argv_merger[s_contj++]="-p";
460             switch(vob->divxmultipass)
461             {
462                 case 3:
463                     p_argv_merger[s_contj++]="3";
464                 break;
465                 case 2:
466                     p_argv_merger[s_contj++]="2";
467                 break;
468                 case 1:
469                     p_argv_merger[s_contj++]="1";
470                 break;
471                 case 0:
472                 default:
473                     p_argv_merger[s_contj++]="0";
474                 break;
475             }
476         }
477         p_argv[s_cont++]="-d";
478         p_argv_merger[s_contj++]="-d";
479         p_argv_merger_sys[s_contsys++]="-d";
480         if (verbose == 0)
481         {
482             p_argv[s_cont++]="0";
483             p_argv_merger[s_contj++]="0";
484             p_argv_merger_sys[s_contsys++]="0";
485         }
486         else if (verbose==1)
487         {
488             p_argv[s_cont++]="1";
489             p_argv_merger[s_contj++]="1";
490             p_argv_merger_sys[s_contsys++]="1";
491         }
492         else
493         {
494             p_argv[s_cont++]="2";
495             p_argv_merger[s_contj++]="2";
496             p_argv_merger_sys[s_contsys++]="2";
497         }
498         if (p_file_to_open !=NULL)
499         {
500             p_argv[s_cont++]="-f";
501             p_argv[s_cont++]=p_file_to_open; /*video/audio out file name*/
502             p_argv_merger[s_contj++]="-f";
503             p_argv_merger[s_contj++]=p_file_to_open; /*video/audio out file name*/
504             p_argv_merger_sys[s_contsys++]="-f";
505             p_argv_merger_sys[s_contsys++]=p_file_to_open;
506         }
507         p_argv_merger_sys[s_contsys++]="-L";    /*need to create system list every time*/
508         if (p_merger_conf->s_build_only_list)
509             p_argv_merger[s_contj++]="-L";
510         if ((verbose_flag & TC_INFO)||(verbose_flag & TC_DEBUG))
511             tc_log_info(MOD_NAME, "P1=%s, P2=%s (%d %d %d)",
512                 p_par1,p_par2,p_pvm_conf->s_nproc,
513                 p_pvm_conf->s_max_proc,
514                 p_pvm_conf->s_num_frame_task);
515         if (p_handle==NULL)
516         {
517             if((p_handle=f_init_pvm_func("open",NULL))==NULL)
518             {
519                 pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
520                 return TC_ERROR;
521             }
522         }
523         p_argv[s_cont++]="-t";
524         p_argv_merger[s_contj++]="-t";
525         p_argv_merger_sys[s_contsys++]="-t";
526         if (p_pvm_conf->s_system_merger.s_build_only_list==2)
527             p_argv_merger_sys[s_contsys++]="multisystem";
528         else
529             p_argv_merger_sys[s_contsys++]="system";
530         if (s_sys_merger_started==0)
531         {
532             memset((char *)&s_pvm_single_proc_system,'\0',sizeof(pvm_func_t));
533             s_pvm_single_proc_system.p_slave_tids=&s_merger_tid_system[0];  /*data for the merger process*/
534             s_pvm_single_proc_system.s_nproc=1;
535             s_pvm_single_proc_system.s_current_tid=0;     /*data for the merger process*/
536             p_merger_sys_tid=(int *)&s_merger_tid_system[0];
537         }
538         if(param->flag == TC_VIDEO)
539         {
540             p_argv[s_cont++]="video"; /*video parameter*/
541             p_argv_merger[s_contj++]="video"; /*video parameter*/
542             memset((char *)&s_pvm_fun_video,'\0',sizeof(pvm_func_t));
543             p_pvm_fun=&s_pvm_fun_video;
544             p_merger_tid=&s_merger_tid_video[0];
545             memset((char *)&s_pvm_single_proc_video,'\0',sizeof(pvm_func_t));
546             p_pvm_single_proc=&s_pvm_single_proc_video;
547             p_pvm_single_proc->p_slave_tids=&s_merger_tid_video[0]; /*data for the merger process*/
548         }
549         else
550         {
551             p_argv[s_cont++]="audio"; /*audio parameter*/
552             p_argv_merger[s_contj++]="audio";/*audio parameter*/
553             memset((char *)&s_pvm_fun_audio,'\0',sizeof(pvm_func_t));
554             p_pvm_fun=&s_pvm_fun_audio;
555             p_merger_tid=&s_merger_tid_audio[0];
556             memset((char *)&s_pvm_single_proc_audio,'\0',sizeof(pvm_func_t));
557             p_pvm_single_proc=&s_pvm_single_proc_audio;
558             p_pvm_single_proc->p_slave_tids=&s_merger_tid_audio[0]; /*data for the merger process*/
559         }
560         p_pvm_single_proc->s_nproc=1;               /*data for the merger process*/
561         p_pvm_single_proc->s_current_tid=0; /*data for the merger process*/
562         if (f_pvm_master_start_stop("open","tcpvmexportd",p_argv,p_pvm_conf->s_nproc,p_pvm_conf->s_max_proc,p_pvm_fun)==NULL)
563         {
564             PVM_DEINIT;
565             pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
566             return TC_ERROR;
567         }
568         memset((char *)&s_version,'\0',MAX_BUF);
569         tc_snprintf((char *)&s_version,MAX_BUF,"%s",EXPORT_PVM_VERSION);
570         if((f_pvm_multi_send(strlen(&s_version[0]),(char *)&s_version[0],PVM_CHECK_VERSION,p_pvm_fun))==-1)
571         {
572             (pvm_func_t*)f_pvm_master_start_stop("close","tcpvmexportd",(char **)0,p_pvm_conf->s_nproc,p_pvm_conf->s_max_proc,p_pvm_fun);
573             PVM_DEINIT;
574             pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
575             return TC_ERROR;
576         }
577         if (p_pvm_conf->s_system_merger.p_hostname!=NULL)
578         {
579             if ((s_sys_merger_started==0)&&(s_msys==0))
580             {
581                 s_sys_merger_started=1; /*execute only 1 time*/
582                 s_msys=1;
583                 if ((*p_merger_sys_tid=f_pvm_start_single_process("tcpvmexportd",p_argv_merger_sys,p_pvm_conf->s_system_merger.p_hostname)) ==-1)
584                 {
585                     (pvm_func_t*)f_pvm_master_start_stop("close","tcpvmexportd",(char **)0,p_pvm_conf->s_nproc,p_pvm_conf->s_max_proc,p_pvm_fun);
586                     PVM_DEINIT;
587                     pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
588                     return TC_ERROR;
589                 }
590                 if (verbose_flag & TC_DEBUG)
591                     tc_log_info(MOD_NAME, "System merger tid %d",*p_merger_sys_tid);
592                 /*send the output file name*/
593                 if(f_pvm_send(strlen(p_file_to_open),(char *)p_file_to_open,PVM_JOIN_OPT_INIT,s_pvm_single_proc_system.s_current_tid,&s_pvm_single_proc_system)==-1)
594                 {
595                     f_pvm_stop_single_process(*p_merger_sys_tid);
596                     (pvm_func_t*)f_pvm_master_start_stop("close","tcpvmexportd",(char **)0,p_pvm_conf->s_nproc,p_pvm_conf->s_max_proc,p_pvm_fun);
597                     PVM_DEINIT;
598                     pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
599                     return TC_ERROR;
600                 }
601             }
602         }
603         if ((*p_merger_tid=f_pvm_start_single_process("tcpvmexportd",p_argv_merger,p_merger_conf->p_hostname)) ==-1)
604         {
605             if (s_sys_merger_started==1)
606                 s_sys_merger_started--;
607             else if (s_sys_merger_started==0)
608                 f_pvm_stop_single_process(*p_merger_sys_tid);
609             (pvm_func_t*)f_pvm_master_start_stop("close","tcpvmexportd",(char **)0,p_pvm_conf->s_nproc,p_pvm_conf->s_max_proc,p_pvm_fun);
610             PVM_DEINIT;
611             pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
612             return TC_ERROR;
613         }
614         if (verbose_flag & TC_DEBUG)
615             tc_log_info(MOD_NAME, "MOD_INIT stop f_pvm_start_single_process");
616         if (verbose_flag & TC_DEBUG)
617             tc_log_info(MOD_NAME, "MOD_INIT start PVM_INIT_SKED");
618         if((f_pvm_multi_send(sizeof(int),(char *)&p_pvm_conf->s_num_frame_task,PVM_INIT_SKED,p_pvm_fun))==-1)
619         {
620             f_pvm_stop_single_process(*p_merger_tid);
621             if (s_sys_merger_started==1)
622                 s_sys_merger_started--;
623             else if (s_sys_merger_started==0)
624                 f_pvm_stop_single_process(*p_merger_sys_tid);
625             (pvm_func_t*)f_pvm_master_start_stop("close","tcpvmexportd",(char **)0,p_pvm_conf->s_nproc,p_pvm_conf->s_max_proc,p_pvm_fun);
626             PVM_DEINIT;
627             pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
628             return TC_ERROR;
629         }
630         if (verbose_flag & TC_DEBUG)
631             tc_log_info(MOD_NAME, "MOD_INIT stop PVM_INIT_SKED");
632         if (verbose_flag & TC_DEBUG)
633         {
634             if(param->flag == TC_VIDEO)
635                 tc_log_info(MOD_NAME, "Video merger tid %d",*p_merger_tid);
636             else
637                 tc_log_info(MOD_NAME, "Audio merger tid %d",*p_merger_tid);
638         }
639         if((f_pvm_multi_send(sizeof(int),(char *)p_merger_tid,PVM_INIT_JOIN,p_pvm_fun))==-1)    /*send the merger tid*/
640         {
641             f_pvm_stop_single_process(*p_merger_tid);
642             if (s_sys_merger_started==1)
643                 s_sys_merger_started--;
644             else if (s_sys_merger_started==0)
645                 f_pvm_stop_single_process(*p_merger_sys_tid);
646             (pvm_func_t*)f_pvm_master_start_stop("close","tcpvmexportd",(char **)0,p_pvm_conf->s_nproc,p_pvm_conf->s_max_proc,p_pvm_fun);
647             PVM_DEINIT;
648             pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
649             return TC_ERROR;
650         }
651         /*initial send of the vob structures to the slave processes*/
652         p_vob_buffer=f_vob_pack("open",vob,&s_vob_buffer_size);
653         if (vob->divxmultipass==2)
654         {
655             if (verbose_flag & TC_DEBUG)
656                 tc_log_info(MOD_NAME, "enter in preinit msg");
657             for(s_cont=0;s_cont<p_pvm_fun->s_nproc;s_cont++)
658             {
659                 if(f_pvm_send(sizeof(int),(char *)&s_cont,PVM_EXP_OPT_PREINIT,s_cont,p_pvm_fun)==-1)
660                 {
661                     f_pvm_stop_single_process(*p_merger_tid);
662                     if (s_sys_merger_started==1)
663                         s_sys_merger_started--;
664                     else if (s_sys_merger_started==0)
665                         f_pvm_stop_single_process(*p_merger_sys_tid);
666                     (pvm_func_t*)f_pvm_master_start_stop("close","tcpvmexportd",(char **)0,p_pvm_conf->s_nproc,p_pvm_conf->s_max_proc,p_pvm_fun);
667                     PVM_DEINIT;
668                     pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
669                     return TC_ERROR;
670                 }
671             }
672             if (verbose_flag & TC_DEBUG)
673                 tc_log_info(MOD_NAME, "exit from preinit msg");
674         }
675         if((f_pvm_multi_send(s_vob_buffer_size,p_vob_buffer,PVM_EXP_OPT_INIT,p_pvm_fun))==-1)
676         {
677             f_pvm_stop_single_process(*p_merger_tid);
678             if (s_sys_merger_started==1)
679                 s_sys_merger_started--;
680             else if (s_sys_merger_started==0)
681                 f_pvm_stop_single_process(*p_merger_sys_tid);
682             (pvm_func_t*)f_pvm_master_start_stop("close","tcpvmexportd",(char **)0,p_pvm_conf->s_nproc,p_pvm_conf->s_max_proc,p_pvm_fun);
683             PVM_DEINIT;
684             pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
685             return TC_ERROR;
686         }
687         (char *)f_vob_pack("close",NULL,&s_vob_buffer_size);
688         if(f_pvm_send(strlen(p_file_to_open),(char *)p_file_to_open,PVM_JOIN_OPT_INIT,p_pvm_single_proc->s_current_tid,p_pvm_single_proc)==-1)
689         {
690             f_pvm_stop_single_process(*p_merger_tid);
691             if (s_sys_merger_started==1)
692                 s_sys_merger_started--;
693             else if (s_sys_merger_started==0)
694                 f_pvm_stop_single_process(*p_merger_sys_tid);
695             (pvm_func_t*)f_pvm_master_start_stop("close","tcpvmexportd",(char **)0,p_pvm_conf->s_nproc,p_pvm_conf->s_max_proc,p_pvm_fun);
696             PVM_DEINIT;
697             pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
698             return TC_ERROR;
699         }
700         if (s_msys==1)
701         {
702             if(f_pvm_send(sizeof(int),(char *)p_merger_sys_tid,PVM_MERGER_INIT,p_pvm_single_proc->s_current_tid,p_pvm_single_proc)==-1)
703             {
704                 f_pvm_stop_single_process(*p_merger_tid);
705                 if (s_sys_merger_started==1)
706                     s_sys_merger_started--;
707                 else if (s_sys_merger_started==0)
708                     f_pvm_stop_single_process(*p_merger_sys_tid);
709                 (pvm_func_t*)f_pvm_master_start_stop("close","tcpvmexportd",(char **)0,p_pvm_conf->s_nproc,p_pvm_conf->s_max_proc,p_pvm_fun);
710                 PVM_DEINIT;
711                 pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
712                 return TC_ERROR;
713             }
714         }
715     }
716     pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
717     if (verbose_flag & TC_DEBUG)
718         tc_log_info(MOD_NAME, "exit from MOD_INIT");
719     return TC_OK;
720 }
721 
722 
723 /* ------------------------------------------------------------
724  *
725  * encode and export
726  *
727  * ------------------------------------------------------------*/
728 
729 MOD_encode
730 {
731     static int s_video_cont=0,s_audio_cont=0,s_video_seq=0,s_audio_seq=0;
732     static char *p_video_buffer=NULL,*p_audio_buffer=NULL;
733     pvm_func_t *p_pvm_fun=NULL;
734     char *p_buffer=NULL;
735     int s_seq,s_cont=0;
736     int *p_merger_tid=0,*p_merger_sys_tid=0;
737     int s_null_module;
738 
739     pthread_mutex_lock(&s_channel_lock);    /*this is the only way to make my module work with nultithreads: need to change all the code*/
740     p_merger_sys_tid=(int *)&s_merger_tid_system[0];
741         if(param->flag == TC_VIDEO)
742         {
743         s_null_module=s_null_video_module;
744         if (!s_null_module)
745         {
746             p_pvm_fun=&s_pvm_fun_video;
747             p_buffer=p_video_buffer;
748             s_seq=s_video_seq;
749             p_merger_tid=&s_merger_tid_video[0];
750             s_cont=s_video_cont;
751         }
752     }
753     else
754         {
755         s_null_module=s_null_audio_module;
756         if (!s_null_module)
757         {
758             p_pvm_fun=&s_pvm_fun_audio;
759             p_buffer=p_audio_buffer;
760             s_seq=s_audio_seq;
761             p_merger_tid=&s_merger_tid_audio[0];
762             s_cont=s_audio_cont;
763         }
764     }
765     if (!s_null_module)
766     {
767         if (p_buffer==NULL)
768         {
769             p_buffer=(char *)malloc(sizeof(transfer_t)+param->size);
770             f_pvm_balancer("open",p_pvm_fun,0,param->flag);
771         }
772         (int)f_pvm_set_send(s_seq); /*set the seq number*/
773         ac_memcpy(p_buffer,(char *)param,sizeof(transfer_t));
774         ac_memcpy(p_buffer+sizeof(transfer_t),(char *)param->buffer,param->size);
775         if((s_seq=f_pvm_send((sizeof(transfer_t)+param->size),(char *)p_buffer,PVM_EXP_OPT_ENCODE,p_pvm_fun->s_current_tid,p_pvm_fun))==-1)
776         {
777             f_pvm_stop_single_process(*p_merger_tid);
778             if (s_sys_merger_started==1)
779                 s_sys_merger_started--;
780             else if (s_sys_merger_started==0)
781                 f_pvm_stop_single_process(*p_merger_sys_tid);
782             PVM_CLOSE;
783             pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
784             return TC_ERROR;
785         }
786         if (verbose_flag & TC_DEBUG)
787         {
788             if(param->flag == TC_VIDEO)
789                 tc_log_info(MOD_NAME,"Send %d video sequence number",s_seq);
790             else
791                 tc_log_info(MOD_NAME,"Send %d audio sequence number",s_seq);
792         }
793         f_pvm_balancer("set-seq",p_pvm_fun,s_seq,param->flag); /*the tid in s_tid_pos now elab the seq*/
794         if (s_cont<p_pvm_conf->s_num_frame_task)
795         {
796             s_cont++;
797         }
798         else
799         {
800             (int)f_pvm_set_send(s_seq); /*set the prev. seq number*/
801             if((s_seq=f_pvm_send(0,(char *)0,PVM_EXP_OPT_RESTART_ENCODE1,p_pvm_fun->s_current_tid,p_pvm_fun))==-1)
802             {
803                 f_pvm_stop_single_process(*p_merger_tid);
804                 if (s_sys_merger_started==1)
805                     s_sys_merger_started--;
806                 else if (s_sys_merger_started==0)
807                     f_pvm_stop_single_process(*p_merger_sys_tid);
808                 PVM_CLOSE;
809                 pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
810                 return TC_ERROR;
811             }
812             f_pvm_balancer("first-free",p_pvm_fun,s_seq,param->flag);
813             if((s_seq=f_pvm_send(0,(char *)0,PVM_EXP_OPT_RESTART_ENCODE2,p_pvm_fun->s_current_tid,p_pvm_fun))==-1) /*automatic increment of seq*/
814             {
815                 f_pvm_stop_single_process(*p_merger_tid);
816                 if (s_sys_merger_started==1)
817                     s_sys_merger_started--;
818                 else if (s_sys_merger_started==0)
819                     f_pvm_stop_single_process(*p_merger_sys_tid);
820                 PVM_CLOSE;
821                 pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
822                 return TC_ERROR;
823             }
824             s_cont=0;
825         }
826         if(param->flag == TC_VIDEO)
827         {
828             p_video_buffer=p_buffer;
829             s_video_seq=s_seq;
830             s_video_cont=s_cont;
831         }
832         else
833         {
834             p_audio_buffer=p_buffer;
835             s_audio_seq=s_seq;
836             s_audio_cont=s_cont;
837         }
838     }
839     pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
840     return TC_OK;
841 }
842 
843 
844 /* ------------------------------------------------------------
845  *
846  * stop codec
847  *
848  * ------------------------------------------------------------*/
849 
850 MOD_stop
851 {
852     pvm_func_t *p_pvm_fun=NULL;
853     int *p_merger_tid=0,*p_merger_sys_tid=0;
854     int s_null_module;
855     static int s_msys=0;
856 
857     p_merger_sys_tid=(int *)&s_merger_tid_system[0];
858     pthread_mutex_lock(&s_channel_lock);    /*this is the only way to make my module work with nultithreads: need to change all the code*/
859         if(param->flag == TC_VIDEO)
860         {
861         s_null_module=s_null_video_module;
862         if (!s_null_module)
863         {
864             p_pvm_fun=&s_pvm_fun_video;
865             p_merger_tid=&s_merger_tid_video[0];
866             }
867         }
868     else
869         {
870         s_null_module=s_null_audio_module;
871         if (!s_null_module)
872         {
873             p_pvm_fun=&s_pvm_fun_audio;
874             p_merger_tid=&s_merger_tid_audio[0];
875             }
876         }
877     if (!s_null_module)
878     {
879         if (p_handle!=NULL)
880         {
881             if (p_pvm_fun!=NULL)
882             {
883                 (int)f_pvm_multi_send(0,(char *)0,PVM_EXP_OPT_STOP,p_pvm_fun);
884                 f_pvm_stop_single_process(*p_merger_tid);
885                 if (s_sys_merger_started!=-1)
886                 {
887                     if (s_msys==0)
888                     {
889                         s_msys=1;
890                         f_pvm_stop_single_process(*p_merger_sys_tid);
891                         memset((char *)&s_pvm_single_proc_system,'\0',sizeof(pvm_func_t));
892                         s_merger_tid_system[0]=-1;
893                     }
894                 }
895                 f_pvm_balancer("close",p_pvm_fun,0,param->flag);
896                 (pvm_func_t*)f_pvm_master_start_stop("close","tcpvmexportd",(char **)0,p_pvm_conf->s_nproc,p_pvm_conf->s_max_proc,p_pvm_fun);
897             }
898             PVM_DEINIT;
899             if (s_init_check==0)
900                 p_handle=NULL;
901         }
902         if(param->flag == TC_VIDEO)
903         {
904             memset((char *)&s_pvm_fun_video,'\0',sizeof(pvm_func_t));
905             s_merger_tid_video[0]=-1;
906         }
907         else
908         {
909             memset((char *)&s_pvm_fun_video,'\0',sizeof(pvm_func_t));
910             s_merger_tid_audio[0]=-1;
911         }
912     }
913     pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
914     return TC_OK;
915 }
916 
917 
918 /* ------------------------------------------------------------
919  *
920  * close codec
921  *
922  * ------------------------------------------------------------*/
923 
924 MOD_close
925 {
926     int s_seq=0,s_dummy,s_dummy1,s_rc;
927     pvm_func_t *p_pvm_fun=NULL;
928     int *p_merger_tid=0,*p_merger_sys_tid=0;
929     pvm_func_t *p_pvm_single_proc=NULL;
930     int s_null_module;
931     static int s_msys=0;
932 
933     p_merger_sys_tid=(int *)&s_merger_tid_system[0];
934     pthread_mutex_lock(&s_channel_lock);    /*this is the only way to make my module work with nultithreads: need to change all the code*/
935         if(param->flag == TC_VIDEO)
936         {
937         s_null_module=s_null_video_module;
938         if (!s_null_module)
939         {
940             p_pvm_fun=&s_pvm_fun_video;
941             p_merger_tid=&s_merger_tid_video[0];
942             p_pvm_single_proc=&s_pvm_single_proc_video;
943         }
944         }
945     else
946         {
947         s_null_module=s_null_audio_module;
948         if (!s_null_module)
949         {
950             p_pvm_fun=&s_pvm_fun_audio;
951             p_merger_tid=&s_merger_tid_audio[0];
952             p_pvm_single_proc=&s_pvm_single_proc_audio;
953         }
954         }
955     if (!s_null_module)
956     {
957         if((s_seq=f_pvm_send(0,(char *)0,PVM_EXP_OPT_RESTART_ENCODE1,p_pvm_fun->s_current_tid,p_pvm_fun))==-1)  /*flush the buffer*/
958         {
959             f_pvm_stop_single_process(*p_merger_tid);
960             if (s_sys_merger_started==1)
961                 s_sys_merger_started--;
962             else if (s_sys_merger_started==0)
963                 f_pvm_stop_single_process(*p_merger_sys_tid);
964             PVM_CLOSE;
965             pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
966             return TC_ERROR;
967         }
968         if((f_pvm_multi_send(0,(char *)0,PVM_EXP_OPT_CLOSE,p_pvm_fun))==-1)
969         {
970             f_pvm_stop_single_process(*p_merger_tid);
971             if (s_sys_merger_started==1)
972                 s_sys_merger_started--;
973             else if (s_sys_merger_started==0)
974                 f_pvm_stop_single_process(*p_merger_sys_tid);
975             PVM_CLOSE;
976             pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
977             return TC_ERROR;
978         }
979         if((s_seq=f_pvm_send(0,(char *)0,PVM_JOIN_OPT_RUN,0,p_pvm_single_proc))==-1) /*s_seq not really used*/
980         {
981             f_pvm_stop_single_process(*p_merger_tid);
982             if (s_sys_merger_started==1)
983                 s_sys_merger_started--;
984             else if (s_sys_merger_started==0)
985                 f_pvm_stop_single_process(*p_merger_sys_tid);
986             PVM_CLOSE;
987             pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
988             return TC_ERROR;
989         }
990         if (verbose_flag & TC_DEBUG)
991         {
992             if(param->flag == TC_VIDEO)
993                 tc_log_info(MOD_NAME,"Waiting for video merger task (seq %d) termination...",s_seq);
994             else
995                 tc_log_info(MOD_NAME,"Waiting for audio merger task (seq %d) termination...",s_seq);
996         }
997         (int)f_pvm_set_recv(s_seq); /*set the last s_seq send*/
998         (int)f_pvm_recv(&s_dummy,(char *)&s_dummy1,&s_rc);
999         if (s_rc)
1000         {
1001             tc_log_warn(MOD_NAME,"Can't close destination file");
1002             f_pvm_stop_single_process(*p_merger_tid);
1003             if (s_sys_merger_started==1)
1004                 s_sys_merger_started--;
1005             else if (s_sys_merger_started==0)
1006                 f_pvm_stop_single_process(*p_merger_sys_tid);
1007             PVM_CLOSE;
1008             pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
1009             return TC_ERROR;
1010         }
1011         if (verbose_flag & TC_DEBUG)
1012             tc_log_info(MOD_NAME, "done.");
1013         if (s_sys_merger_started!=-1)
1014         {
1015             if((s_seq=f_pvm_send(0,(char *)0,PVM_JOIN_OPT_SENDFILE,0,p_pvm_single_proc))==-1) /*s_seq not really used*/
1016             {
1017                 f_pvm_stop_single_process(*p_merger_tid);
1018                 if (s_sys_merger_started==1)
1019                     s_sys_merger_started--;
1020                 else if (s_sys_merger_started==0)
1021                     f_pvm_stop_single_process(*p_merger_sys_tid);
1022                 PVM_CLOSE;
1023                 pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
1024                 return TC_ERROR;
1025             }
1026         }
1027         if (s_msys)
1028         {
1029             if (verbose_flag & TC_DEBUG)
1030                 tc_log_info(MOD_NAME, "Waiting for system merger build list...");
1031             (int)f_pvm_set_recv(PVM_MSG_ENDTASK_SYSTEM);    /*wait for system merger end task*/
1032             (int)f_pvm_recv(&s_dummy,(char *)&s_dummy1,&s_rc);
1033             if (verbose_flag & TC_DEBUG)
1034                 tc_log_info(MOD_NAME, "done.");
1035             if (s_rc)
1036             {
1037                 tc_log_warn(MOD_NAME,"Can't close destination file");
1038                 f_pvm_stop_single_process(*p_merger_tid);
1039                 PVM_CLOSE;
1040                 pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
1041                 return TC_ERROR;
1042             }
1043             if ((p_pvm_conf->s_system_merger.p_hostname!=NULL)&&(p_pvm_conf->s_system_merger.s_build_only_list!=1)) /*do it for 0 and 2*/
1044             {
1045                 if((s_seq=f_pvm_send(0,(char *)0,PVM_JOIN_OPT_RUN,0,&s_pvm_single_proc_system))==-1) /*s_seq not really used*/
1046                 {
1047                     f_pvm_stop_single_process(*p_merger_tid);
1048                     f_pvm_stop_single_process(*p_merger_sys_tid);
1049                     PVM_CLOSE;
1050                     pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
1051                     return TC_ERROR;
1052                 }
1053                 if (verbose_flag & TC_DEBUG)
1054                     tc_log_info(MOD_NAME,"Waiting for system merger task (seq %d) termination...",s_seq);
1055                 (int)f_pvm_set_recv(s_seq); /*set the last s_seq send*/
1056                 (int)f_pvm_recv(&s_dummy,(char *)&s_dummy1,&s_rc);
1057                 if (s_rc)
1058                 {
1059                     tc_log_warn(MOD_NAME,"Can't close destination file");
1060                     f_pvm_stop_single_process(*p_merger_tid);
1061                     PVM_CLOSE;
1062                     pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
1063                     return TC_ERROR;
1064                 }
1065                 if (verbose_flag & TC_DEBUG)
1066                     tc_log_info(MOD_NAME,"done.");
1067             }
1068         }
1069         if (s_sys_merger_started!=-1)
1070             s_msys=1;
1071     }
1072     pthread_mutex_unlock(&s_channel_lock);  /*this is the only way to make my module work with nultithreads: need to change all the code*/
1073     return TC_OK;
1074 }
1075 
1076 
1077