1 /***************************************************************************
2  avsfilter.cpp  -  description
3  -------------------
4  begin                : 28-04-2008
5  copyright            : (C) 2008-2013 by fahr
6  email                : fahr at inbox dot ru
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 #include <string>
18 #ifndef AVS_WINE_BINARY_PATH
19 #error "AVS_WINE_BINARY_PATH not set!!!"
20 #endif
21 
22 #include "ADM_default.h"
23 #include "ADM_coreVideoFilter.h"
24 #include "ADM_files.h"
25 #include "DIA_factory.h"
26 #include "errno.h"
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <fcntl.h>
35 #include <time.h>
36 #include <signal.h>
37 #include <pthread.h>
38 
39 #include "strnew.h"
40 #include "avspipecomm.h"
41 #include "avsfilterparam.h"
42 #include "avsfilterparam_desc.cpp"
43 #include "avsfilter.h"
44 #include "cdebug.h"
45 
46 #define AVSFILTER_VERSION_INFO "AvsFilter, ver 0.12"
47 #define NOCOMPILE26
48 
49 bool use_adv_protocol_avsfilter_to_pipesource = false;
50 bool use_adv_protocol_avsloader_to_avsfilter = false;
51 
52 static WINE_LOADER *first_loader = NULL;
53 static AVSTerminate term;
54 
55 #define MAXPATHLEN 512
56 
57 /**
58  * several functions for realize link of objects
59  */
find_object(int order,const char * avs_loader,const char * avs_script,time_t script_ctime,time_t script_mtime,FilterInfo * input_info,bool * full)60 WINE_LOADER *find_object(int order,
61                          const char *avs_loader, const char *avs_script,
62                          time_t script_ctime, time_t script_mtime,
63                          FilterInfo *input_info,
64                          bool *full)
65 {
66   WINE_LOADER *res = first_loader;
67 
68   while (res != NULL)
69   {
70     // check order first
71     if (res->order == order)
72     {
73       // after we check other params
74       if (!strcmp((char*)res->param.avs_loader.c_str(), avs_loader) &&
75           (!avs_script ||
76            !strcmp((char*)res->param.avs_script.c_str(), avs_script)) &&
77           res->input_info.width == input_info->width &&
78           res->input_info.height == input_info->height &&
79           res->param.script_ctime == script_ctime &&
80           res->param.script_mtime == script_mtime &&
81           res->input_info.frameIncrement == input_info->frameIncrement &&
82           res->input_info.totalDuration == input_info->totalDuration)
83       {
84 /*        DEBUG_PRINTF("find_object : find %s %s\n",
85                      (char*)res->_param.avs_loader,
86                      (char*)res->_param.avs_script);*/
87         if (full) *full = true;
88       }
89       else
90       {
91 /*        DEBUG_PRINTF("find_object fail: %s %s %dx%d [%d - %d] ftime %X:%X != %s %s %dx%d [%d - %d] ftime %lX:%lX\n",
92                      (char*)res->_param.avs_loader,
93                      (char*)res->_param.avs_script,
94                      res->input_info.width,
95                      res->input_info.height,
96                      res->input_info.orgFrame, res->input_info.orgFrame + res->input_info.nb_frames,
97                      res->_param.script_ctime, res->_param.script_mtime,
98                      avs_loader, avs_script, input_info->width, input_info->height,
99                      input_info->orgFrame, input_info->orgFrame + input_info->nb_frames,
100                      script_ctime, script_mtime);*/
101         if (full) *full = false;
102       }
103       break;
104     }
105     res = (WINE_LOADER *)res->next_wine_loader;
106   }
107   return res;
108 }
109 
print_objects(void)110 void print_objects(void)
111 {
112   WINE_LOADER *res = first_loader;
113 
114   while (res != NULL)
115   {
116 /*    DEBUG_PRINTF("print_objects : %s %s %dx%d [%d - %d]\n",
117                  (char*)res->_param.avs_loader,
118                  (char*)res->_param.avs_script,
119                  res->input_info.width,
120                  res->input_info.height,
121                  res->input_info.orgFrame, res->input_info.orgFrame + res->input_info.nb_frames);*/
122     res = (WINE_LOADER *)res->next_wine_loader;
123   }
124   return;
125 }
126 
delete_object(WINE_LOADER * obj)127 void delete_object(WINE_LOADER *obj)
128 {
129   WINE_LOADER *res = first_loader;
130 
131   if (res == obj)
132   {
133     first_loader = (WINE_LOADER *) obj->next_wine_loader;
134     return;
135   }
136 
137   while (res != NULL)
138   {
139     if (res->next_wine_loader == obj)
140     {
141       res->next_wine_loader = obj->next_wine_loader;
142       break;
143     }
144     res = (WINE_LOADER *)res->next_wine_loader;
145   }
146 }
147 
add_object(WINE_LOADER * obj)148 void add_object(WINE_LOADER *obj)
149 {
150   WINE_LOADER *res = first_loader;
151   DEBUG_PRINTF("avsfilter : add_object start, res = %X\n", res);
152   if (!res)
153   {
154     first_loader = obj;
155     obj->next_wine_loader = NULL;
156     return;
157   }
158 
159   while (res != NULL)
160   {
161     if (res->next_wine_loader == NULL)
162     {
163       res->next_wine_loader = obj;
164       obj->next_wine_loader = NULL;
165       break;
166     }
167     res = (WINE_LOADER *) res->next_wine_loader;
168   }
169   DEBUG_PRINTF("avsfilter : add_object end\n");
170 }
171 
172 //********************************************
173 
deinit_pipe(AVS_PIPES * avsp)174 void deinit_pipe(AVS_PIPES *avsp)
175 {
176   if (avsp->hpipe != -1)
177   {
178     close(avsp->hpipe);
179     avsp->hpipe = -1;
180   }
181 
182   // if both link to pipename and pipename string exist
183   DEBUG_PRINTF("avsfilter : deinit_pipe %X\n", avsp->pipename);
184   DEBUG_PRINTF("avsfilter : deinit_pipe %s\n", avsp->pipename);
185   remove(avsp->pipename);
186   if (avsp->pipename && *avsp->pipename)
187   {
188     void *ptr = avsp->pipename;
189     avsp->pipename = NULL;
190     ADM_dealloc (ptr);
191   }
192 }
193 
deinit_pipes(AVS_PIPES * avsp,int num)194 void deinit_pipes(AVS_PIPES *avsp, int num)
195 {
196   int i;
197   for (i = 0; i < num; i++) deinit_pipe(&avsp[i]);
198 }
199 
200 #define MAX_PATH 1024
201 
init_pipes(AVS_PIPES * avsp,int num,FILE * pfile)202 bool init_pipes (AVS_PIPES *avsp, int num, FILE *pfile)
203 {
204   int i;
205   for (i = 0; i < num; i++)
206   {
207     char sname[MAX_PATH];
208 
209     if (fscanf(pfile, "%s\n", sname) != 1) DEBUG_PRINTF_RED("fscanf error\n");
210     else if (!(avsp[i].pipename = strnew(sname))) DEBUG_PRINTF_RED("strnew error\n");
211     else if (remove(avsp[i].pipename)) DEBUG_PRINTF_RED("error remove file\n");
212     else if (mkfifo(avsp[i].pipename, 0600))
213      DEBUG_PRINTF_RED("mkfifo error create fifo file %s, errno %d\n",
214 	         avsp[i].pipename, errno);
215     else continue;
216 
217     deinit_pipes(avsp, i);
218     return false;
219   }
220 
221   return true;
222 }
223 
open_pipes(AVS_PIPES * avsp,int num)224 bool open_pipes(AVS_PIPES *avsp, int num)
225 {
226   int i;
227   for (i = 0; i < num; i++)
228   {
229     DEBUG_PRINTF("avsfilter : try to open %s fifo\n", avsp[i].pipename);
230     if ((avsp[i].hpipe = open(avsp[i].pipename, avsp[i].flags)) == -1)
231     {
232       DEBUG_PRINTF_RED("avsfilter : failed open errno %d\n", errno);
233       deinit_pipe(&avsp[i]);
234       deinit_pipes(avsp, i);
235       return false;
236     }
237   }
238 
239   DEBUG_PRINTF("all pipes open ok\n");
240 
241   return true;
242 }
243 
pipe_test_filter(int hr,int hw)244 bool pipe_test_filter(int hr, int hw)
245 {
246 
247   uint32_t test_send = (uint32_t) time(NULL);
248   uint32_t test_r1 = 0;
249 
250   int sz1;
251 
252   DEBUG_PRINTF("avsfilter : pipe_test_filter prewrite\n");
253 
254   sz1 = write(hw, &test_send, sizeof(uint32_t));
255 
256   if (sz1 != sizeof(uint32_t)) return false;
257 
258   DEBUG_PRINTF("avsfilter : pipe_test_filter preread\n");
259 
260   sz1 = read(hr, &test_r1, sizeof(uint32_t));
261 
262   if (sz1 != sizeof(uint32_t) || (test_r1 != test_send)) return false;
263 
264   return true;
265 }
266 
267 bool open_pipes_ok, wine_loader_down = false;
268 
~AVSTerminate()269 AVSTerminate::~AVSTerminate()
270 {
271   WINE_LOADER *cur_loader = first_loader;
272   int i = 0;
273   DEBUG_PRINTF("Call terminate!!!\n");
274 
275   if (cur_loader)
276     do {
277       DEBUG_PRINTF("Count %d\n", i++);
278 
279       if (cur_loader->avs_pipes[PIPE_LOADER_WRITE].hpipe != -1)
280       {
281         send_cmd(cur_loader->avs_pipes[PIPE_LOADER_WRITE].hpipe,
282                  UNLOAD_AVS_SCRIPT, NULL, 0);
283         DEBUG_PRINTF("UNLOAD_AVS_SCRIPT try\n");
284       }
285 
286       if (cur_loader->avs_pipes[PIPE_LOADER_WRITE].hpipe != -1)
287       {
288         send_cmd(cur_loader->avs_pipes[PIPE_LOADER_WRITE].hpipe,
289                  UNLOAD_AVS_LOADER, NULL, 0);
290         DEBUG_PRINTF("UNLOAD_AVS_LOADER try\n");
291       }
292 
293       deinit_pipes(cur_loader->avs_pipes, CMD_PIPE_NUM);
294     } while((cur_loader = (WINE_LOADER*)cur_loader->next_wine_loader) != NULL);
295 }
296 
parse_wine_stdout(void * arg)297 void *parse_wine_stdout(void *arg)
298 {
299   char sname[MAX_PATH];
300   TPARSER *tp = (TPARSER *)arg;
301   FILE *pfile = tp->pfile;
302   AVS_PIPES copy_pipes [CMD_PIPE_NUM];
303   int i;
304   for (i = 0; i < CMD_PIPE_NUM; i++)
305   {
306     memcpy (&copy_pipes[i], &tp->avs_pipes[i], sizeof(AVS_PIPES));
307     if ((copy_pipes[i].flags & O_ACCMODE) == O_RDONLY)
308       copy_pipes[i].flags = (copy_pipes[i].flags & ~O_ACCMODE) | O_WRONLY;
309     else
310       if ((copy_pipes[i].flags & O_ACCMODE) == O_WRONLY)
311         copy_pipes[i].flags = (copy_pipes[i].flags & ~O_ACCMODE) | O_RDONLY;
312 
313     DEBUG_PRINTF("avsfilter : new.flags %X, old.flags %X\n",
314            copy_pipes[i].flags, tp->avs_pipes[i].flags);
315   }
316 
317   wine_loader_down = false;
318 
319   if (pfile)
320   {
321     time_t t = time(NULL);
322     DEBUG_PRINTF("avsfilter : pthread time %s\n",
323            ctime(&t));
324     DEBUG_PRINTF("pthread start ok\n");
325     while(fgets(sname, MAX_PATH, pfile) != NULL)
326 #ifdef DEBUGMSG
327       printf("%s", sname);
328 #else
329     ;
330 #endif
331     DEBUG_PRINTF("End parse\n");
332     pclose(pfile);
333 
334     wine_loader_down = true;
335 
336     // if pipes not open completely, then simple open from thread for close
337     if (!open_pipes_ok)
338     {
339       DEBUG_PRINTF("avsfilter : loader down, try to close waiting (for open) main thread\n");
340       if (open_pipes((AVS_PIPES*)&copy_pipes, CMD_PIPE_NUM))
341       {
342         DEBUG_PRINTF("avsfilter : open ok, try to deinit\n");
343         //deinit_pipes((AVS_PIPES*)&copy_pipes, CMD_PIPE_NUM);
344         DEBUG_PRINTF("avsfilter : deinit done\n");
345       }
346     }
347 
348   }
349   return NULL;
350 }
351 
wine_start(const char * wine_app,const char * avsloader,AVS_PIPES * avs_pipes,int pipe_timeout)352 bool wine_start(const char *wine_app, const char *avsloader, AVS_PIPES *avs_pipes, int pipe_timeout)
353 {
354   char sname[MAX_PATH];
355   struct stat st;
356   sprintf(sname, "%s %s %d", wine_app, avsloader, pipe_timeout);
357 
358   FILE *pfile = popen(sname, "r");
359   if (!pfile)
360   {
361    DEBUG_PRINTF_RED("avsfilter : popen failed, errno %d, failed start app is : [%s]\n", errno, sname);
362    return false;
363   }
364 
365   if (fscanf(pfile, "%s\n", sname) != 1 ||
366       stat(sname, &st) ||
367       !S_ISDIR(st.st_mode))
368   {
369     DEBUG_PRINTF_RED("avsfilter : tmpdirname [%s] failed, errno %d[stat %d isdir %d]\n", sname, errno, stat(sname, &st), S_ISDIR(st.st_mode));
370     pclose(pfile);
371     return false;
372   }
373 
374   DEBUG_PRINTF("avsfilter : good tmpdirname %s\n", sname);
375 
376   if (!init_pipes(avs_pipes, CMD_PIPE_NUM, pfile))
377   {
378     DEBUG_PRINTF_RED("init_pipes failed\n");
379     pclose(pfile);
380     return false;
381   }
382 
383   time_t t = time(NULL);
384   DEBUG_PRINTF("avsfilter : precreate thread time %s\n",
385          ctime(&t));
386   pthread_t thread;
387   TPARSER tp = { avs_pipes, pfile };
388 
389   open_pipes_ok = false;
390 
391   if (pthread_create(&thread, NULL, parse_wine_stdout, &tp))
392   {
393     DEBUG_PRINTF_RED("Cannot pthread started...Errno %d\n",errno);
394     deinit_pipes(avs_pipes, CMD_PIPE_NUM);
395     return false;
396   }
397 
398   t = time(NULL);
399   DEBUG_PRINTF("avsfilter : preopen time %s\n",
400          ctime(&t));
401 
402   if (!open_pipes(avs_pipes, CMD_PIPE_NUM) || wine_loader_down)
403   {
404     open_pipes_ok = true;
405     DEBUG_PRINTF_RED("open_pipes failed\n");
406     deinit_pipes(avs_pipes, CMD_PIPE_NUM);
407     return false;
408   }
409 
410   open_pipes_ok = true;
411 
412   if (pipe_test_filter (avs_pipes[PIPE_LOADER_READ].hpipe,
413                         avs_pipes[PIPE_FILTER_WRITE].hpipe))
414   {
415     DEBUG_PRINTF("avsfilter : test pipe to filter ok\n");
416 
417     if (pipe_test_filter (avs_pipes[PIPE_LOADER_READ].hpipe,
418                           avs_pipes[PIPE_LOADER_WRITE].hpipe))
419     {
420       DEBUG_PRINTF("avsfilter : test pipe to loader ok\n");
421     }
422     else
423      goto error_pipe_test;
424   }
425   else
426   {
427     error_pipe_test:
428     DEBUG_PRINTF_RED("Error test read/write pipes\n");
429     deinit_pipes(avs_pipes, CMD_PIPE_NUM);
430     return false;
431   }
432 
433   DEBUG_PRINTF("wine start is ok\n");
434   return true;
435 }
436 
avs_start(FilterInfo * info,FilterInfo * avisynth_info,const char * fname,AVS_PIPES * avs_pipes,PITCH_DATA * pd_pipe_source,PITCH_DATA * pd_avsloader)437 bool avs_start(FilterInfo *info, FilterInfo *avisynth_info,
438                const char *fname, AVS_PIPES *avs_pipes, PITCH_DATA *pd_pipe_source, PITCH_DATA *pd_avsloader)
439 {
440  DEBUG_PRINTF("avsfilter : avs_start()\n");
441  DEBUG_PRINTF("avsfilter : %X %X %s %X\n",
442               avs_pipes[PIPE_LOADER_WRITE].hpipe,
443               avs_pipes[PIPE_FILTER_WRITE].hpipe,
444               fname, info);
445  DEBUG_PRINTF("avsfilter : avs_start info : frameIncrement %lu totalDuration %llu\n",
446               info->frameIncrement, info->totalDuration);
447 
448  ADV_Info aii, aio;
449  aii.width = info->width;
450  aii.height = info->height;
451  aii.nb_frames = info->totalDuration / info->frameIncrement;
452  aii.encoding = MAGIC_ADV_PROTOCOL_VAL;
453  aii.codec = 0;
454  aii.fps1000 = ADM_Fps1000FromUs(info->frameIncrement);
455  aii.orgFrame = 0;
456  DEBUG_PRINTF("avsfilter : send ADV_Info to avsloader [fps1000 = %d, nb_frames = %d]\n", aii.fps1000, aii.nb_frames);
457  if (!send_cmd(avs_pipes[PIPE_LOADER_WRITE].hpipe,
458                 LOAD_AVS_SCRIPT, fname,
459                 strlen(fname) + sizeof("\0")) ||
460       !send_cmd(avs_pipes[PIPE_FILTER_WRITE].hpipe,
461                 SET_CLIP_PARAMETER, &aii,
462                 sizeof(aii)))
463   {
464     DEBUG_PRINTF_RED("avsfilter : cannot set script name or set clip parameters\n");
465     deinit_pipes(avs_pipes, CMD_PIPE_NUM);
466     return false;
467   }
468 
469   // get avisynth frame info
470  PIPE_MSG_HEADER msg;
471  if (!receive_cmd(avs_pipes[PIPE_LOADER_READ].hpipe, &msg))
472  {
473   DEBUG_PRINTF_RED("avsfilter : cannot receive command (SEND_PITCH_DATA_PIPE_SOURCE, OR SET_CLIP_PARAMETER)\n");
474   deinit_pipes(avs_pipes, CMD_PIPE_NUM);
475   return false;
476  }
477 
478  switch (msg.avs_cmd)
479  {
480  case SEND_PITCH_DATA_PIPE_SOURCE:
481      if (!receive_data(avs_pipes[PIPE_LOADER_READ].hpipe, &msg, pd_pipe_source))
482      {
483       DEBUG_PRINTF_RED("avsfilter : cannot receive SEND_PITCH_DATA_PIPE_SOURCE\n");
484       deinit_pipes(avs_pipes, CMD_PIPE_NUM);
485       return false;
486      }
487      DEBUG_PRINTF("avsfilter : receive SEND_PITCH_DATA_PIPE_SOURCE YUV = %d %d %d\n", pd_pipe_source->pitchY, pd_pipe_source->pitchU, pd_pipe_source->pitchV);
488      if (!receive_cmd(avs_pipes[PIPE_LOADER_READ].hpipe, &msg) ||
489          msg.avs_cmd != SET_CLIP_PARAMETER)
490      {
491       DEBUG_PRINTF_RED("avsfilter : cannot receive SET_CLIP_PARAMETER header message\n");
492       deinit_pipes(avs_pipes, CMD_PIPE_NUM);
493       return false;
494      }
495  case SET_CLIP_PARAMETER:
496      if (!receive_data(avs_pipes[PIPE_LOADER_READ].hpipe, &msg, &aio))
497      {
498       DEBUG_PRINTF_RED("avsfilter : cannot receive avisynth clip parameters\n");
499       deinit_pipes(avs_pipes, CMD_PIPE_NUM);
500       return false;
501      }
502      break;
503  default :
504      DEBUG_PRINTF_RED("avsfilter : receive unknown command %d\n", msg.avs_cmd);
505      deinit_pipes(avs_pipes, CMD_PIPE_NUM);
506      return false;
507      break;
508  }
509 
510   DEBUG_PRINTF("avsfilter : receive ADV_Info from avsloader [fps1000 = %d, nb_frames = %d]\n", aio.fps1000, aio.nb_frames);
511   avisynth_info->width = aio.width;
512   avisynth_info->height = aio.height;
513   avisynth_info->frameIncrement = ADM_UsecFromFps1000(aio.fps1000);
514   avisynth_info->totalDuration = aio.nb_frames * avisynth_info->frameIncrement;
515   if (aio.encoding == MAGIC_ADV_PROTOCOL_VAL)
516   {
517    DEBUG_PRINTF("avsfilter : send GET_PITCH_DATA to avsloader\n");
518    if (!send_cmd(avs_pipes[PIPE_LOADER_WRITE].hpipe,
519                  GET_PITCH_DATA, NULL, 0))
520    {
521     DEBUG_PRINTF_RED("avsfilter : cannot send GET_PITCH_DATA\n");
522     deinit_pipes(avs_pipes, CMD_PIPE_NUM);
523     return false;
524    }
525   }
526 
527   // correct avisynth_info for span of frames, calculate fps change metrics
528 /*  float k_fps;
529   k_fps = float(avisynth_info->frameIncrement) / float(info->frameIncrement);
530   DEBUG_PRINTF("avsfilter : FPS change metrics %f\n", k_fps);
531   avisynth_info->nb_frames = int (info->nb_frames * k_fps);
532   avisynth_info->orgFrame = int (info->orgFrame * k_fps);
533   DEBUG_PRINTF("avsfilter : Calculate new span for avisynth script [%d - %d]\n",
534                avisynth_info->orgFrame,avisynth_info->orgFrame + avisynth_info->nb_frames);*/
535   return true;
536 }
537 #ifdef VERSION_2_5
538 
539 DECLARE_VIDEO_FILTER(avsfilter,
540                      0,0,12,
541                      ADM_UI_ALL,
542                      VF_MISC,
543                      "avsfilter",
544                      "avsfilter",
545                      "Use avisynth script as video filter.");
546 
547 #else
548 extern "C"
549 {
550   SCRIPT_CREATE(FILTER_create_fromscript,avsfilter,avsParam);
551   BUILD_CREATE(FILTER_create,avsfilter);
552 
FILTER_getName(void)553   char *FILTER_getName(void)
554   {
555     return AVSFILTER_VERSION_INFO;
556   }
557 
FILTER_getDesc(void)558   char *FILTER_getDesc(void)
559   {
560     return "This filter do intermediate processing via avisynth script";
561   }
562 
FILTER_getVersion(void)563   uint32_t FILTER_getVersion(void)
564   {
565     return 1;
566   }
FILTER_getAPIVersion(void)567   uint32_t FILTER_getAPIVersion(void)
568   {
569     return ADM_FILTER_API_VERSION;
570   }
571 }
572 #endif
573 
getConfiguration(void)574 const char *avsfilter::getConfiguration(void)
575 {
576   static char buf[MAXPATHLEN];
577 
578   snprintf((char *)buf, MAXPATHLEN, "wine_app : %s\n loader : %s\n script : %s\npipe timeout %d\n",
579            param.wine_app.c_str(), param.avs_loader.c_str(), param.avs_script.c_str(), param.pipe_timeout);
580   return buf;
581 }
582 
583 bool  avsfilter_config_jserialize(const char *file, const avsfilter_config *key);
584 bool  avsfilter_config_jdeserialize(const char *file, const ADM_paramList *tmpl,avsfilter_config *key);
585 
configure(void)586 bool avsfilter::configure(void)
587 {
588  DEBUG_PRINTF("avsfilter : before dialog init\n");
589  print_objects();
590 
591 #define PX(x) &(param.x)
592 std::string pWineApp=std::string(param.wine_app);
593 std::string pLoaderFile=std::string(param.avs_loader);
594 std::string pAvsScript=std::string(param.avs_script);
595 
596 
597  diaElemFile wine_app(0,pWineApp,
598                       QT_TRANSLATE_NOOP("avsfilter","_wine app file:"), NULL,
599                       QT_TRANSLATE_NOOP("avsfilter","Select wine filename[wine/cedega/etc.]"));
600  diaElemFile loaderfile(0,pLoaderFile,
601                         QT_TRANSLATE_NOOP("avsfilter","_loader file:"), NULL,
602                         QT_TRANSLATE_NOOP("avsfilter","Select loader filename[avsload.exe]"));
603  diaElemFile avsfile(0,pAvsScript,
604                      QT_TRANSLATE_NOOP("avsfilter","_avs file:"), NULL,
605                      QT_TRANSLATE_NOOP("avsfilter","Select avs filename[*.avs]"));
606  diaElemUInteger pipe_timeout(PX(pipe_timeout),QT_TRANSLATE_NOOP("avsfilter","_pipe timeout:"),1,30);
607 
608  diaElem *elems[4]={&wine_app, &loaderfile, &avsfile, &pipe_timeout};
609 
610  if( diaFactoryRun(QT_TRANSLATE_NOOP("avsfilter","AvsFilter config"), 4, elems))
611  {
612   bool res = false;
613     param.wine_app=ADM_strdup(pWineApp.c_str()); // 3x memleak
614     param.avs_loader=ADM_strdup(pLoaderFile.c_str());
615     param.avs_script=ADM_strdup(pAvsScript.c_str());
616 
617 
618   DEBUG_PRINTF("avsfilter : configure before SetParameters\n");
619 
620   // if script/loader names are exist, then taste config
621   if (param.avs_loader.size() &&
622       param.avs_script.size() &&
623       param.wine_app.size())
624   {
625    struct stat st;
626    if (stat((char*)param.avs_script.c_str(), &st) != 0)
627    {
628     DEBUG_PRINTF_RED("avsfilter : cannot stat script file\n");
629     return 0;
630    }
631 
632    param.script_mtime = st.st_mtime; // store timestamp
633    param.script_ctime = st.st_ctime;
634 
635    print_objects();
636    res = SetParameters(&param);
637    if (res)
638     avsfilter_config_jserialize(prefs_name, &param);
639 
640    DEBUG_PRINTF("avsfilter : configure before save prefs [%s][%s]\n",
641                 param.avs_script.c_str(), param.avs_loader.c_str());
642    // if setparameters are ok and (therefore) avs_script and avs_loader exist
643    // we store this parameters in filter preferences
644    DEBUG_PRINTF("avsfilter : after save prefs info : frameIncrement %lu totalDuration %llu\n",
645                 info.frameIncrement, info.totalDuration);
646 
647    DEBUG_PRINTF("avsfilter : configure exit ok\n");
648    return res;
649   }
650  }
651  return 0;
652 }
653 
654 /**
655     \fn getTimeRange
656 */
getTimeRange(uint64_t * startTime,uint64_t * endTime)657 bool avsfilter::getTimeRange(uint64_t *startTime, uint64_t *endTime)
658 {
659     *startTime = 0;
660     *endTime = info.totalDuration;
661     return true;
662 }
663 
664 //#define SET_AVS(i,x,y,z) {wine_loader->avs_pipes[i].pipename = x; wine_loader->avs_pipes[i].hpipe = y; wine_loader->avs_pipes[i].flags = z;}
665 
SetParameters(avsfilter_config * newparam)666 bool avsfilter::SetParameters(avsfilter_config *newparam)
667 {
668   bool full_exact = false;
669   DEBUG_PRINTF("avsfilter : SetParameters\n");
670 
671   // find corresponding loader/script
672   WINE_LOADER *loader = find_object(order,
673                                     newparam->avs_loader.c_str(),
674                                     newparam->avs_script.c_str(),
675                                     newparam->script_ctime, newparam->script_mtime,
676                                     &info,
677                                     &full_exact);
678   // if loader not found
679   if (!loader)
680   {
681     DEBUG_PRINTF("avsfilter : SetParameters no loader found\n");
682     loader = new (WINE_LOADER);
683     loader->avs_pipes[0].flags = O_RDONLY;
684     loader->avs_pipes[1].flags = O_WRONLY;
685     loader->avs_pipes[2].flags = O_WRONLY;
686     loader->RefCounter = 0;
687     loader->param.avs_script = std::string("");
688     loader->param.avs_loader = std::string("");
689 
690     if (!wine_start(newparam->wine_app.c_str(), newparam->avs_loader.c_str(), loader->avs_pipes, newparam->pipe_timeout))
691     {
692       DEBUG_PRINTF_RED("avsfilter : wine_start unsuccessful start!\n");
693       delete loader;
694       deref_wine_loader:
695       if (wine_loader)
696       {
697         wine_loader->RefCounter--;
698         wine_loader = NULL;
699       }
700       return false;
701     }
702 
703     DEBUG_PRINTF("avsfilter : SetParameters success start wine\n");
704     loader->order = order;
705     add_object(loader);
706   }
707 
708   // all parameters are NOT matched [order only]
709   if (!full_exact)
710   {
711     DEBUG_PRINTF("avsfilter : SetParameters !full_exact\n");
712 
713     // matched only order (need reload with new script/geometry/etc)
714     if (!avs_start(&info, &loader->output_info, newparam->avs_script.c_str(), loader->avs_pipes, &pd_pipe_source, &pd_avsloader))
715     {
716       DEBUG_PRINTF_RED("avsfilter : SetParameters fail avs_start\n");
717       delete_object(loader);
718       goto deref_wine_loader;
719     }
720 
721     DEBUG_PRINTF("avsfilter : SetParameters avs_start ok\n");
722     loader->RefCounter = 0;
723     memcpy(&loader->input_info, &info, sizeof(info));
724     loader->param.avs_loader = newparam->avs_loader;
725     loader->param.avs_script = newparam->avs_script;
726     loader->param.script_ctime = newparam->script_ctime; // store timestamp
727     loader->param.script_mtime = newparam->script_mtime;
728   }
729 
730   if (wine_loader && wine_loader != loader) wine_loader->RefCounter--;
731   wine_loader = loader;
732   wine_loader->RefCounter++;
733   out_frame_sz = ((loader->output_info.width * loader->output_info.height) * 3) >>1;
734   // 22.11 fix size of output filter with fullexact found loader
735   info.width = loader->output_info.width;
736   info.height = loader->output_info.height;
737   info.frameIncrement = loader->output_info.frameIncrement;
738   info.totalDuration = loader->output_info.totalDuration;
739   /*  info.fps1000 = loader->output_info.fps1000;
740   info.nb_frames = loader->output_info.nb_frames;
741   info.orgFrame = loader->output_info.orgFrame;*/
742 
743 /*   DEBUG_PRINTF("avsfilter : clip info : geom %d:%d fps1000 %d num_frames %d\n",
744  info.width, info.height, info.fps1000, info.nb_frames);*/
745   DEBUG_PRINTF("avsfilter : clip info : geom %d:%d frameIncrement %lu totalDuration %llu\n",
746                info.width, info.height, info.frameIncrement, info.totalDuration);
747 
748   DEBUG_PRINTF("avsfilter : SetParameters return Ok\n");
749   return true;
750 }
751 
avsfilter(ADM_coreVideoFilter * in,CONFcouple * couples)752 avsfilter::avsfilter(ADM_coreVideoFilter *in,
753                      CONFcouple *couples) : ADM_coreVideoFilter(in,couples)
754 {
755   ADM_assert(in);
756   tmp_buf = NULL;
757   in=in;
758   DEBUG_PRINTF("Create AVSfilter(%X), AVDMGenericVideoStream %X\n", this, in);
759 
760   wine_loader = NULL;
761 //  param = new (avsfilter_config);
762   DEBUG_PRINTF("avsfilter : preconstructor info : frameIncrement %lu totalDuration %llu\n",
763                info.frameIncrement, info.totalDuration);
764   memcpy(&info, previousFilter->getInfo(),sizeof(info));
765   DEBUG_PRINTF("avsfilter : constructor info : frameIncrement %lu totalDuration %llu\n",
766                info.frameIncrement, info.totalDuration);
767 
768 //  info.encoding=1;
769   //vidCache = NULL;
770 
771 #define AVSFILTER_CONFIG_NAME "/avsfilter.config2"
772   std::string psd = ADM_getUserPluginSettingsDir();
773   int sz_prefs_name = strlen (psd.c_str()) + sizeof(AVSFILTER_CONFIG_NAME) + 1;
774   prefs_name = new char [sz_prefs_name];
775   snprintf(prefs_name, sz_prefs_name, "%s%s", psd.c_str(), AVSFILTER_CONFIG_NAME);
776 
777   if (!couples || !ADM_paramLoad(couples,
778                                  avsfilter_config_param,
779                                  &param))
780   {
781    if (!avsfilter_config_jdeserialize(prefs_name, avsfilter_config_param, &param))
782    {
783     param.wine_app = ADM_strdup("wine");
784     param.avs_script = ADM_strdup("test.avs");;
785     param.avs_loader = ADM_strdup(AVS_WINE_BINARY_PATH"/avsload.exe");
786     param.pipe_timeout = 10;
787     param.script_ctime = 0;
788     param.script_mtime = 0;
789    }
790   }
791 
792   DEBUG_PRINTF("avsfilter : constructor info #2: frameIncrement %lu totalDuration %llu\n",
793                info.frameIncrement, info.totalDuration);
794 
795   DEBUG_PRINTF("avsfilter : wine_app %s avsloader %s avsscript %s\n",
796                param.wine_app.c_str(), param.avs_loader.c_str(), param.avs_script.c_str());
797 
798   if (!SetParameters(&param))
799   {
800    DEBUG_PRINTF_RED("avsfilter : SetParameters return false\n");
801    DEBUG_PRINTF("avsfilter : info after error: frameIncrement %lu totalDuration %llu\n",
802                 info.frameIncrement, info.totalDuration);
803    return;
804   }
805 
806   DEBUG_PRINTF("avsfilter : constructor info #3: frameIncrement %lu totalDuration %llu\n",
807                info.frameIncrement, info.totalDuration);
808 
809 #ifndef NOCOMPILE26
810     if (prefs->get(FILTERS_AVSFILTER_WINE_APP, &tmp_str) == RC_OK &&
811         strlen(tmp_str) > 0)
812     {
813       _param->wine_app = (ADM_filename*)ADM_strdup (tmp_str);
814       DEBUG_PRINTF("avsfilter : wine_app from config is %s\n", _param->wine_app);
815       ADM_dealloc(tmp_str);
816     }
817 
818     if (prefs->get(FILTERS_AVSFILTER_AVS_SCRIPT, &tmp_str) == RC_OK &&
819         strlen(tmp_str) > 0)
820     {
821       _param->avs_script = (ADM_filename*)ADM_strdup (tmp_str);
822       DEBUG_PRINTF("avsfilter : avsscript from config is %s\n", _param->avs_script);
823       ADM_dealloc(tmp_str);
824     }
825 
826     if (prefs->get(FILTERS_AVSFILTER_AVS_LOADER, &tmp_str) == RC_OK &&
827         strlen(tmp_str) > 0)
828     {
829       _param->avs_loader = (ADM_filename*)ADM_strdup (tmp_str);
830       DEBUG_PRINTF("avsfilter : avsloader from config is %s\n", _param->avs_loader);
831       ADM_dealloc(tmp_str);
832     }
833     prefs->get(FILTERS_AVSFILTER_PIPE_TIMEOUT, &_param->pipe_timeout);
834 
835     struct stat st;
836     if (_param->avs_script)
837       if (stat((char*)_param->avs_script, &st) != 0)
838       {
839         DEBUG_PRINTF_RED("avsfilter : cannot stat script file\n");
840         return;
841       }
842       else
843       {
844         _param->script_mtime = st.st_mtime; // store timestamp
845         _param->script_ctime = st.st_ctime;
846       }
847   }
848 #endif
849   _uncompressed=new ADMImageDefault(in->getInfo()->width,in->getInfo()->height);
850   ADM_assert(_uncompressed);
851   in_frame_sz = ((_uncompressed->_width * _uncompressed->_height) * 3) >>1;
852   tmp_buf = (unsigned char*)ADM_alloc(PIPE_MAX_TRANSFER_SZ * 2);
853   ADM_assert(tmp_buf);
854   DEBUG_PRINTF("avsfilter : after constructor info : frameIncrement %lu totalDuration %llu\n",
855                info.frameIncrement, info.totalDuration);
856 
857   if (_uncompressed->GetPitch(PLANAR_Y) == pd_pipe_source.pitchY &&
858       _uncompressed->GetPitch(PLANAR_U) == pd_pipe_source.pitchU &&
859       _uncompressed->GetPitch(PLANAR_V) == pd_pipe_source.pitchV)
860   {
861    use_adv_protocol_avsfilter_to_pipesource = true;
862    DEBUG_PRINTF("avsfilter : use_adv_protocol_avsfilter_to_pipesource = true\n");
863   }
864 
865 //  vidCache=new VideoCache(16,in);
866 }
867 
868 avsfilter::~avsfilter()
869 {
870   if (wine_loader)
871   {
872     wine_loader->RefCounter--;
873     if (!wine_loader->RefCounter) wine_loader = NULL;
874   }
875 
876   if (tmp_buf) ADM_dezalloc(tmp_buf);
877   delete [] prefs_name;
878   prefs_name=NULL;
879 
880 /*  if (vidCache)
881   {
882     delete vidCache;
883     vidCache = NULL;
884   }*/
885 }
886 
887 void avsfilter::setCoupledConf( CONFcouple *couples)
888 {
889  DEBUG_PRINTF("avsfilter : setCoupledConf\n");
890  ADM_paramLoad(couples, avsfilter_config_param, &param);
891 }
892 
893 bool avsfilter::getCoupledConf( CONFcouple **couples)
894 {
895   //*couples=new CONFcouple(6);
896 
897 //#define CSET(x)  (*couples)->setCouple((char *)#x,(_param.x))
898  DEBUG_PRINTF("avsfilter : getCoupledConf\n");
899  DEBUG_PRINTF("avsfilter : getCoupledConf info: frameIncrement %lu totalDuration %llu\n",
900               info.frameIncrement, info.totalDuration);
901  bool t =  ADM_paramSave(couples, avsfilter_config_param, &param);
902  DEBUG_PRINTF("avsfilter : getCoupledConf info #2: frameIncrement %lu totalDuration %llu\n",
903               info.frameIncrement, info.totalDuration);
904  return t;
905 
906 /*  CSET(wine_app);
907   CSET(avs_script);
908   CSET(avs_loader);
909   CSET(pipe_timeout);
910   CSET(script_mtime);
911   CSET(script_ctime);*/
912 /*  DEBUG_PRINTF("avsfilter : getCoupledConf end\n");
913   return 1;*/
914 }
915 
916 bool receive_bit_blt(int h,
917                      uint8_t* srcp, int src_pitch,
918                      int row_size, int height)
919 {
920  for (int y = height; y > 0; --y)
921  {
922   if (ppread(h, (void*)srcp, row_size) != row_size) return false;
923   srcp += src_pitch;
924  }
925  return true;
926 }
927 
928 bool send_bit_blt(int h,
929                   uint8_t* srcp, int src_pitch,
930                   int row_size, int height, unsigned char *data)
931 {
932  unsigned char *org_data = data;
933  for (int y = height; y > 0; --y)
934  {
935   int cp_sz;
936   memcpy(data, (void*)srcp, row_size);
937   srcp += src_pitch;
938   data += row_size;
939   cp_sz = data - org_data;
940   if (cp_sz >= PIPE_MAX_TRANSFER_SZ || y == 1)
941   {
942    if (ppwrite(h, (void*)org_data, cp_sz) != cp_sz) return false;
943    else
944    {
945     data = org_data;
946     DEBUG_PRINTF("avsfilter : send_bit_blt copy %d\n", cp_sz);
947    }
948   }
949  }
950  return true;
951 }
952 
953 bool avsfilter::getNextFrame(uint32_t *fn, ADMImage *data)
954 {
955  uint32_t iframe = nextFrame;
956  uint32_t frame, tmpframe;
957  frame = iframe;
958 
959   DEBUG_PRINTF("avsfilter : receive getFrameNumberNoAlloc %d, wine_loader %X\n",
960                frame, wine_loader);
961 
962   // check framenumber
963   if (!wine_loader || ((iframe * wine_loader->output_info.frameIncrement) > wine_loader->output_info.totalDuration))
964   {
965    DEBUG_PRINTF("avsfilter : input framenumber (%d) is out of bounds [time %d > %d] \n", iframe,
966                 iframe * wine_loader->output_info.frameIncrement, wine_loader->output_info.totalDuration);
967    return false;
968   }
969 
970   FRAME_DATA fd = {frame};
971 
972   // send command to get filtered data
973   if (!send_cmd(wine_loader->avs_pipes[PIPE_LOADER_WRITE].hpipe,
974                 use_adv_protocol_avsloader_to_avsfilter ? GET_FRAME_WITH_PITCH : GET_FRAME, (void*)&fd,
975                 sizeof(FRAME_DATA)))
976   {
977     DEBUG_PRINTF_RED("avsfilter : error send GET_FRAME to avsloader\n");
978     return 0;
979   }
980 
981   // read all data from avsloader and pipe dll
982   PIPE_MSG_HEADER msg;
983   while (receive_cmd(wine_loader->avs_pipes[PIPE_LOADER_READ].hpipe, &msg))
984   {
985     switch(msg.avs_cmd)
986     {
987     default:
988             break;
989     case SEND_PITCH_DATA_AVSLOADER:
990         DEBUG_PRINTF("avsfilter : receive SEND_PITCH_DATA_AVSLOADER\n");
991         if (!receive_data(wine_loader->avs_pipes[PIPE_LOADER_READ].hpipe, &msg, &pd_avsloader))
992         {
993          DEBUG_PRINTF_RED("avsfilter : cannot get SEND_PITCH_DATA_AVSLOADER\n");
994          return 0;
995         }
996         DEBUG_PRINTF("avsfilter : receive SEND_PITCH_DATA_AVSLOADER YUV = %d %d %d\n", pd_avsloader.pitchY, pd_avsloader.pitchU, pd_avsloader.pitchV);
997         if (data->GetPitch(PLANAR_Y) == pd_avsloader.pitchY &&
998             data->GetPitch(PLANAR_U) == pd_avsloader.pitchU &&
999             data->GetPitch(PLANAR_V) == pd_avsloader.pitchV)
1000         {
1001          use_adv_protocol_avsloader_to_avsfilter = true;
1002          DEBUG_PRINTF("avsfilter : use_adv_protocol_avsloader_to_avsfilter = true\n");
1003         }
1004         break;
1005 
1006       case GET_FRAME: // this request from pipe_source for input frame(s) to avisynth core
1007         DEBUG_PRINTF("avsfilter : receive GET_FRAME\n");
1008         if (!receive_data(wine_loader->avs_pipes[PIPE_LOADER_READ].hpipe,
1009                           &msg, &fd))
1010         {
1011           DEBUG_PRINTF_RED("\navsfilter : error receive data\n");
1012           return 0;
1013         }
1014 
1015         DEBUG_PRINTF("avsfilter : GET_FRAME number %d\n", fd.frame);
1016         tmpframe = fd.frame;
1017         DEBUG_PRINTF("avsfilter : %d but really get %d\n", fd.frame, tmpframe);
1018         //src=vidCache->getImage(tmpframe);
1019         if (!previousFilter->getNextFrame(&tmpframe, _uncompressed))
1020         {
1021          DEBUG_PRINTF("avsfilter : !!!OOPS!!!\n");
1022          return false;
1023         }
1024 
1025 /*        DEBUG_PRINTF("avsfilter : in frame size %lu pitchYUV %d %d %d, widthYUV %d %d %d, heightYUV %d %d %d\n",
1026                      in_frame_sz, _uncompressed->GetPitch(PLANAR_Y), _uncompressed->GetPitch(PLANAR_U), _uncompressed->GetPitch(PLANAR_V),
1027                      _uncompressed->GetWidth(PLANAR_Y), _uncompressed->GetWidth(PLANAR_U), _uncompressed->GetWidth(PLANAR_V),
1028                      _uncompressed->GetHeight(PLANAR_Y), _uncompressed->GetHeight(PLANAR_U), _uncompressed->GetHeight(PLANAR_V));*/
1029 
1030         if (use_adv_protocol_avsfilter_to_pipesource)
1031         {
1032          uint32_t pitch_data_sizeY = _uncompressed->GetPitch(PLANAR_Y) * _uncompressed->GetHeight(PLANAR_Y);
1033          uint32_t pitch_data_sizeU = _uncompressed->GetPitch(PLANAR_U) * _uncompressed->GetHeight(PLANAR_U);
1034          uint32_t pitch_data_sizeV = _uncompressed->GetPitch(PLANAR_V) * _uncompressed->GetHeight(PLANAR_V);
1035          uint32_t pitch_data_size = pitch_data_sizeY + pitch_data_sizeU + pitch_data_sizeV;
1036          DEBUG_PRINTF("avsfilter : pitch frame size %lu\n", pitch_data_size);
1037 
1038          if (!send_cmd_with_specified_size(wine_loader->avs_pipes[PIPE_FILTER_WRITE].hpipe,
1039                                            PUT_FRAME_WITH_PITCH,
1040                                            (void*)&fd, sizeof(FRAME_DATA), pitch_data_size) ||
1041              ppwrite(wine_loader->avs_pipes[PIPE_FILTER_WRITE].hpipe, _uncompressed->GetReadPtr(PLANAR_Y), pitch_data_sizeY) != pitch_data_sizeY ||
1042              ppwrite(wine_loader->avs_pipes[PIPE_FILTER_WRITE].hpipe, _uncompressed->GetReadPtr(PLANAR_U), pitch_data_sizeU) != pitch_data_sizeU ||
1043              ppwrite(wine_loader->avs_pipes[PIPE_FILTER_WRITE].hpipe, _uncompressed->GetReadPtr(PLANAR_V), pitch_data_sizeV) != pitch_data_sizeV)
1044          {
1045           DEBUG_PRINTF_RED("avsfilter : error send uncompressed PITCH frame to dll\n");
1046           return 0;
1047          }
1048         }
1049         else
1050          // send frame to pipe_source
1051          if (!send_cmd_with_specified_size(wine_loader->avs_pipes[PIPE_FILTER_WRITE].hpipe,
1052                                            PUT_FRAME, (void*)&fd, sizeof(FRAME_DATA), in_frame_sz) ||
1053              !send_bit_blt(wine_loader->avs_pipes[PIPE_FILTER_WRITE].hpipe,
1054                            _uncompressed->GetReadPtr(PLANAR_Y), _uncompressed->GetPitch(PLANAR_Y),
1055                            _uncompressed->GetWidth(PLANAR_Y), _uncompressed->GetHeight(PLANAR_Y), tmp_buf) ||
1056              !send_bit_blt(wine_loader->avs_pipes[PIPE_FILTER_WRITE].hpipe,
1057                            _uncompressed->GetReadPtr(PLANAR_U), _uncompressed->GetPitch(PLANAR_U),
1058                            _uncompressed->GetWidth(PLANAR_U), _uncompressed->GetHeight(PLANAR_U), tmp_buf) ||
1059              !send_bit_blt(wine_loader->avs_pipes[PIPE_FILTER_WRITE].hpipe,
1060                            _uncompressed->GetReadPtr(PLANAR_V), _uncompressed->GetPitch(PLANAR_V),
1061                            _uncompressed->GetWidth(PLANAR_V), _uncompressed->GetHeight(PLANAR_V), tmp_buf))
1062          {
1063           DEBUG_PRINTF_RED("avsfilter : error send uncompressed frame to dll\n");
1064           return 0;
1065          }
1066 
1067         //YPLANE(_uncompressed),
1068         DEBUG_PRINTF("avsfilter : send data ok for frame %d\n", fd.frame);
1069         break;
1070 
1071       case PUT_FRAME_WITH_PITCH:
1072       case PUT_FRAME: // this request from avsload.exe with filtering data after avisynth
1073         DEBUG_PRINTF("avsfilter : receive %s, msg.sz %d\n", msg.avs_cmd == PUT_FRAME_WITH_PITCH ? "PUT_FRAME_WITH_PITCH" : "PUT_FRAME", msg.sz);
1074         if (msg.avs_cmd == PUT_FRAME && msg.sz != out_frame_sz + sizeof(FRAME_DATA))
1075         {
1076          DEBUG_PRINTF_RED("avsfilter : PUT_FRAME error : msg.sz [%d] != out_frame_sz+sizeof(FRAME_DATA) [%d,%d]\n",
1077                            msg.sz, out_frame_sz, sizeof(FRAME_DATA));
1078           return 0;
1079         }
1080 
1081 //        DEBUG_PRINTF("avsfilter : read 1\n");
1082         if (!receive_data_by_size(wine_loader->avs_pipes[PIPE_LOADER_READ].hpipe,
1083                                   &fd, sizeof(FRAME_DATA)))
1084         {
1085           DEBUG_PRINTF_RED("avsfilter : receive data error#1\n");
1086           return 0;
1087         }
1088 
1089 //        ADM_assert(fd.frame == (iframe + info.orgFrame));
1090 
1091 /*        DEBUG_PRINTF("avsfilter : data->GetWidth(PLANAR_Y) %d data->GetHeight(PLANAR_Y) %d\n",
1092                      data->GetWidth(PLANAR_Y), data->GetHeight(PLANAR_Y));
1093         DEBUG_PRINTF("avsfilter : data->GetWidth(PLANAR_U) %d data->GetHeight(PLANAR_U) %d\n",
1094                      data->GetWidth(PLANAR_U), data->GetHeight(PLANAR_U));
1095         DEBUG_PRINTF("avsfilter : data->GetWidth(PLANAR_V) %d data->GetHeight(PLANAR_V) %d\n",
1096                      data->GetWidth(PLANAR_V), data->GetHeight(PLANAR_V));*/
1097 
1098         if (msg.avs_cmd == PUT_FRAME_WITH_PITCH)
1099         {
1100          uint32_t pitch_data_sizeY = data->GetPitch(PLANAR_Y) * data->GetHeight(PLANAR_Y);
1101          uint32_t pitch_data_sizeU = data->GetPitch(PLANAR_U) * data->GetHeight(PLANAR_U);
1102          uint32_t pitch_data_sizeV = data->GetPitch(PLANAR_V) * data->GetHeight(PLANAR_V);
1103          uint32_t pitch_data_size = pitch_data_sizeY + pitch_data_sizeU + pitch_data_sizeV;
1104 
1105          if (msg.sz != (pitch_data_size + sizeof(FRAME_DATA)))
1106          {
1107           DEBUG_PRINTF_RED("avsfilter : PUT_FRAME_WITH_PITCH error : msg.sz [%d] != pitch_data_size + sizeof(FRAME_DATA) [%d,%d]\n",
1108                            msg.sz, pitch_data_size, sizeof(FRAME_DATA));
1109           return 0;
1110         }
1111 
1112          if (ppread(wine_loader->avs_pipes[PIPE_LOADER_READ].hpipe, (void*)data->GetReadPtr(PLANAR_Y), pitch_data_sizeY) != pitch_data_sizeY ||
1113              ppread(wine_loader->avs_pipes[PIPE_LOADER_READ].hpipe, (void*)data->GetReadPtr(PLANAR_U), pitch_data_sizeU) != pitch_data_sizeU ||
1114              ppread(wine_loader->avs_pipes[PIPE_LOADER_READ].hpipe, (void*)data->GetReadPtr(PLANAR_V), pitch_data_sizeV) != pitch_data_sizeV)
1115          {
1116           DEBUG_PRINTF_RED("avsfilter : receive data error for PUT_FRAME_WITH_PITCH\n");
1117           return 0;
1118          }
1119         }
1120         else
1121         {
1122   //       DEBUG_PRINTF("avsfilter : read %d frame number Y plane\n", fd.frame);
1123          if (!receive_bit_blt(wine_loader->avs_pipes[PIPE_LOADER_READ].hpipe,
1124                               data->GetWritePtr(PLANAR_Y), data->GetPitch(PLANAR_Y),
1125                               data->GetWidth(PLANAR_Y), data->GetHeight(PLANAR_Y)))
1126          {
1127           DEBUG_PRINTF_RED("avsfilter : receive data error#2\n");
1128           return 0;
1129          }
1130 
1131 //         DEBUG_PRINTF("avsfilter : read %d frame number U plane\n", fd.frame);
1132          if (!receive_bit_blt(wine_loader->avs_pipes[PIPE_LOADER_READ].hpipe,
1133                               data->GetWritePtr(PLANAR_U), data->GetPitch(PLANAR_U),
1134                               data->GetWidth(PLANAR_U), data->GetHeight(PLANAR_U)))
1135          {
1136           DEBUG_PRINTF_RED("avsfilter : receive data error#3\n");
1137           return 0;
1138          }
1139 //         DEBUG_PRINTF("avsfilter : read %d frame number V plane\n", fd.frame);
1140          if (!receive_bit_blt(wine_loader->avs_pipes[PIPE_LOADER_READ].hpipe,
1141                               data->GetWritePtr(PLANAR_V), data->GetPitch(PLANAR_V),
1142                               data->GetWidth(PLANAR_V), data->GetHeight(PLANAR_V)))
1143          {
1144           DEBUG_PRINTF_RED("avsfilter : receive data error#4\n");
1145           return 0;
1146          }
1147         }
1148 //        *len = out_frame_sz;
1149         DEBUG_PRINTF("avsfilter : copy data\n");
1150         DEBUG_PRINTF("avsfilter : data parameters %d:%d\n",
1151                      data->_width, data->_height);
1152         data->copyInfo(_uncompressed);
1153         data->Pts = _uncompressed->Pts;
1154         //        vidCache->unlockAll();
1155         *fn=nextFrame;
1156         nextFrame++;
1157         return true;
1158         break;
1159     }
1160   }
1161   return false;
1162 }
1163