]> git.vomp.tv Git - vompclient.git/blob - videowin.cc
HDTV for Windows
[vompclient.git] / videowin.cc
1 /*
2     Copyright 2004-2005 Chris Tallon
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 */
20
21
22
23 #include "videowin.h"
24 #include "log.h"
25 #include "dssourcefilter.h"
26 #include "dsallocator.h"
27 #include "vdr.h"
28 #include "osdwin.h"
29 #include "audiowin.h"
30 #include "wwinvideofilter.h"
31 #include "wwinvideoh264filter.h"
32 #include "wtabbar.h"
33 #include "woptionpane.h"
34 #include "i18n.h"
35 #include "demuxer.h"
36
37 #include <Mfapi.h>
38 #include <mferror.h>
39
40 void AdjustWindow();
41
42
43
44 VideoWin::VideoWin()
45 {
46   dsinited=false;
47   dsgraphbuilder=NULL;
48   dsmediacontrol=NULL;
49   dsrenderer=NULL;
50   dsrefclock=NULL;
51   dsmediafilter=NULL;
52   dsbasicaudio=NULL;
53   sourcefilter=NULL;
54   allocatorvmr=NULL;
55   cr_time=0;
56   lastaudiomode=MPTYPE_MPEG_AUDIO;
57   //lastaudiomode=MPTYPE_AC3;
58   dsvmrsurfnotify=NULL;
59   filtermutex=CreateMutex(NULL,FALSE,NULL);
60   offsetnotset=true;
61   offsetvideonotset=true;
62   offsetaudionotset=true;
63   startoffset=0;
64   lastrefaudiotime=0;
65   lastrefvideotime=0;
66   lastreftimeRT=0;
67   lastreftimePTS=0;
68   firstsynched=false;
69   cur_audio_media_sample=NULL;
70   cur_video_media_sample=NULL;
71   videoon=true;
72   audioon=true;
73   audiovolume=0;
74   pseudotvsize=0;
75   videoposx=0;
76   videoposy=0;
77   aud_type=Audio::MPEG2_PES;
78   iframemode=false;//We are not in Iframe mode at begining
79   vmrdeinterlacing=2;//Best
80   videofilterselected=-1;
81   videoH264filterselected=-1;
82   currentpresenter=EVR;
83
84
85
86
87 }
88
89 VideoWin::~VideoWin()
90 {
91   CleanupDS();
92   CloseHandle(filtermutex);
93   unsigned int i;
94   for (i=0;i<videofilterlist.size();i++)
95   {
96    if (videofilterlist[i].displayname) delete [] videofilterlist[i].displayname;
97    if (videofilterlist[i].friendlyname) delete [] videofilterlist[i].friendlyname;
98   }
99   videofilterlist.clear();
100
101   for (i=0;i<videoH264filterlist.size();i++)
102   {
103    if (videoH264filterlist[i].displayname) delete [] videoH264filterlist[i].displayname;
104    if (videoH264filterlist[i].friendlyname) delete [] videoH264filterlist[i].friendlyname;
105   }
106   videoH264filterlist.clear();
107
108
109
110
111   instance = NULL;
112 }
113
114 int VideoWin::init(UCHAR tformat)
115 {
116   if (initted) return 0;
117
118   initted = 1;
119   tvsize=Video::ASPECT16X9; //Internally Vomp should think we are a 16:9 TV
120   videoposx=0;
121   videoposy=0;
122   initFilterDatabase();
123   initH264FilterDatabase();
124
125   if (!setFormat(tformat)){ shutdown(); return 0; }
126   return 1;
127 }
128
129
130
131 int VideoWin::setTVsize(UCHAR ttvsize)
132 {
133   pseudotvsize=ttvsize;
134   return 1;
135 }
136
137 int VideoWin::setDefaultAspect()
138 {
139   return setAspectRatio(Video::ASPECT4X3);
140 }
141
142 int VideoWin::shutdown()
143 {
144   if (!initted) return 0;
145   initted = 0;
146   return 1;
147 }
148
149 int VideoWin::setFormat(UCHAR tformat)
150 {
151   if (!initted) return 0;
152   if ((tformat != PAL) && (tformat != NTSC)) return 0;
153   format = tformat;
154   if (format == NTSC)
155   {
156     screenWidth = 720;
157     screenHeight = 480;
158   }
159   if (format == PAL)
160   {
161     screenWidth = 720;
162     screenHeight = 576;
163   }
164
165   return 1;
166 }
167
168 int VideoWin::setConnection(UCHAR tconnection)
169 {
170   if (!initted) return 0;
171   if ((tconnection != COMPOSITERGB) && (tconnection != SVIDEO)) return 0;
172   connection = tconnection;
173
174   return 1;
175 }
176
177 int VideoWin::setAspectRatio(UCHAR taspectRatio)
178 {
179   if (!initted) return 0;
180   if ((taspectRatio != ASPECT4X3) && (taspectRatio != ASPECT16X9)) return 0;
181   aspectRatio = taspectRatio;
182   AdjustWindow();
183   return 1;
184 }
185
186 int VideoWin::setMode(UCHAR tmode)
187 {
188   if (!initted) return 0;
189
190   //if ((tmode == LETTERBOX) && (tvsize == ASPECT16X9)) return 0; // invalid mode
191
192   if ((tmode != NORMAL) && (tmode != LETTERBOX) && (tmode != UNKNOWN2) && (tmode != QUARTER) && (tmode != EIGHTH)
193       && (tmode != ZOOM) && (tmode != UNKNOWN6)) return 0;
194   mode = tmode;
195   videoposx=0;
196   videoposy=0;
197   AdjustWindow();
198
199   return 1;
200 }
201
202 int VideoWin::signalOff()
203 {
204   return 1;
205 }
206
207 int VideoWin::signalOn()
208 {
209   return 1;
210 }
211
212 int VideoWin::setSource()
213 {
214   if (!initted) return 0;
215
216   return 1;
217 }
218
219 int VideoWin::setPosition(int x, int y)
220 {
221   if (!initted) return 0;
222   if (mode==QUARTER || mode==EIGHTH) {
223   videoposx=x;
224   videoposy=y;
225   }
226   return 1;
227 }
228
229 int VideoWin::sync()
230 {
231   if (!initted) return 0;
232
233   return 1;
234 }
235 void VideoWin::initFilterDatabase()
236 {
237     /* This method should determine all availiable DirectShow Filters */
238     IFilterMapper2* filtmap=NULL;
239     HRESULT result;
240     result = CoCreateInstance(CLSID_FilterMapper2,NULL,CLSCTX_INPROC,
241                 IID_IFilterMapper2,(void**)&filtmap);
242     if (result != S_OK)
243     {
244         Log::getInstance()->log("VideoWin", Log::ERR , "Unable to create FilterMapper!");
245         return;
246     }
247     /* Wishlist, what Mediatypes do we want */
248     GUID mtypesin[]={MEDIATYPE_Video,MEDIASUBTYPE_MPEG2_VIDEO};
249     IEnumMoniker *myenum;
250     result = filtmap->EnumMatchingFilters(&myenum,0,TRUE,MERIT_DO_NOT_USE+1,
251                     TRUE,1,mtypesin,NULL,NULL,FALSE,TRUE,0,NULL,NULL,NULL);
252     if (result != S_OK)
253     {
254         filtmap->Release();
255         Log::getInstance()->log("VideoWin", Log::ERR , "Unable to enum Filters!");
256         return;
257     }
258     ULONG gethowmany;
259     IMoniker * moni;
260     while(myenum->Next(1,&moni,&gethowmany)==S_OK)
261     {
262         VideoFilterDesc desc;
263         ZeroMemory(&desc,sizeof(desc));
264    
265         LPOLESTR string;
266         moni->GetDisplayName(0,0,&string);
267         desc.displayname=new char[wcslen(string)+1];
268         wcstombs(desc.displayname,string,wcslen(string)+1);
269         CoTaskMemFree(string);
270         IPropertyBag *bag;
271         if (moni->BindToStorage(0,0,IID_IPropertyBag,(void**)&bag) == S_OK)
272         {
273             VARIANT vari;
274             VariantInit(&vari);
275             result = bag->Read(L"FriendlyName",&vari,NULL);
276             if (result == S_OK)
277             {
278                 desc.friendlyname=new char[wcslen(vari.bstrVal)+1];
279                 wcstombs(desc.friendlyname,vari.bstrVal,wcslen(vari.bstrVal)+1);
280             }
281             VariantClear(&vari);
282             bag->Release();
283
284         }
285         
286        
287         videofilterlist.push_back(desc);
288        
289
290         
291         moni->Release();
292        // bctx->Release();
293     }
294     int i;
295     videofilterselected=-1;
296     
297     
298   
299     myenum->Release();
300
301
302
303     filtmap->Release();
304 }
305
306 void VideoWin::initH264FilterDatabase()
307 {
308     /* This method should determine all availiable DirectShow Filters */
309     IFilterMapper2* filtmap=NULL;
310     HRESULT result;
311     result = CoCreateInstance(CLSID_FilterMapper2,NULL,CLSCTX_INPROC,
312                 IID_IFilterMapper2,(void**)&filtmap);
313     if (result != S_OK)
314     {
315         Log::getInstance()->log("VideoWin", Log::ERR , "Unable to create FilterMapper!");
316         return;
317     }
318     /* Wishlist, what Mediatypes do we want */
319     GUID mtypesin[]={MEDIATYPE_Video,MEDIASUBTYPE_H264};
320     IEnumMoniker *myenum;
321     result = filtmap->EnumMatchingFilters(&myenum,0,TRUE,MERIT_DO_NOT_USE+1,
322                     TRUE,1,mtypesin,NULL,NULL,FALSE,TRUE,0,NULL,NULL,NULL);
323     if (result != S_OK)
324     {
325         filtmap->Release();
326         Log::getInstance()->log("VideoWin", Log::ERR , "Unable to enum Filters!");
327         return;
328     }
329     ULONG gethowmany;
330     IMoniker * moni;
331     while(myenum->Next(1,&moni,&gethowmany)==S_OK)
332     {
333         VideoFilterDesc desc;
334         ZeroMemory(&desc,sizeof(desc));
335    
336         LPOLESTR string;
337         moni->GetDisplayName(0,0,&string);
338         desc.displayname=new char[wcslen(string)+1];
339         wcstombs(desc.displayname,string,wcslen(string)+1);
340         CoTaskMemFree(string);
341         IPropertyBag *bag;
342         if (moni->BindToStorage(0,0,IID_IPropertyBag,(void**)&bag) == S_OK)
343         {
344             VARIANT vari;
345             VariantInit(&vari);
346             result = bag->Read(L"FriendlyName",&vari,NULL);
347             if (result == S_OK)
348             {
349                 desc.friendlyname=new char[wcslen(vari.bstrVal)+1];
350                 wcstombs(desc.friendlyname,vari.bstrVal,wcslen(vari.bstrVal)+1);
351             }
352             VariantClear(&vari);
353             bag->Release();
354
355         }
356         
357        
358         videoH264filterlist.push_back(desc);
359        
360
361         
362         moni->Release();
363        // bctx->Release();
364     }
365     int i;
366     videoH264filterselected=-1;
367     
368     
369   
370     myenum->Release();
371
372
373
374     filtmap->Release();
375 }
376
377 bool VideoWin::loadOptionsfromServer(VDR* vdr)
378 {
379     char *name=vdr->configLoad("DirectShow","VideoFilter");
380     
381     if (name != NULL) 
382     {
383         for (int i = 0;i <videofilterlist.size();i++)
384         {
385             if (strcmp(name,videofilterlist[i].displayname)==0)
386             {
387                 videofilterselected = i;
388                 break;
389             }
390         }
391    }
392    name=vdr->configLoad("DirectShow","VideoH264Filter");
393     
394     if (name != NULL) 
395     {
396         for (int i = 0;i <videoH264filterlist.size();i++)
397         {
398             if (strcmp(name,videoH264filterlist[i].displayname)==0)
399             {
400                 videoH264filterselected = i;
401                 break;
402             }
403         }
404    }
405    name=vdr->configLoad("DirectShow","VMR9DeinterlacingMode");
406    if (name != NULL) 
407    {
408        if (STRCASECMP(name,"NoMix")==0)  {
409            vmrdeinterlacing=0;
410        } else if (STRCASECMP(name,"None")==0)  {
411            vmrdeinterlacing=1;
412        } else if (STRCASECMP(name,"Best")==0)  {
413            vmrdeinterlacing=2;
414        } else if (STRCASECMP(name,"Bob")==0)  {
415            vmrdeinterlacing=3;
416        } else if (STRCASECMP(name,"Weave")==0)  {
417            vmrdeinterlacing=4;
418        }
419    }
420
421    name=vdr->configLoad("DirectShow", "VideoPresenter");
422    if (name!=NULL) {
423        if (STRCASECMP(name,"VMR9")==0) {
424            currentpresenter=VMR9;
425            } else if (STRCASECMP(name,"EVR")==0) {
426            currentpresenter=EVR;
427        } 
428    }
429    if (!((OsdWin*)Osd::getInstance())->IsEvrSupported()) {
430            currentpresenter=VMR9;
431    }
432
433    name=vdr->configLoad("DirectGraphics", "StretchFiltering");
434    if (name!=NULL) {
435        if (STRCASECMP(name,"None")==0) {
436            ((OsdWin*)Osd::getInstance())->setFilterType(D3DTEXF_NONE);
437        } else if (STRCASECMP(name,"Point")==0) {
438            ((OsdWin*)Osd::getInstance())->setFilterType(D3DTEXF_POINT);
439        } else if (STRCASECMP(name,"Linear")==0) {
440            ((OsdWin*)Osd::getInstance())->setFilterType(D3DTEXF_LINEAR);
441        }
442    }
443
444    
445
446
447    return true;
448
449 }
450
451 bool VideoWin::handleOptionChanges(Option* option)
452 {
453     if( Video::handleOptionChanges(option)) return true;
454     switch(option->id) {
455         case 1: {
456             if (STRCASECMP(option->options[option->userSetChoice],"None")==0) {
457                 ((OsdWin*)Osd::getInstance())->setFilterType(D3DTEXF_NONE);
458             } else if (STRCASECMP(option->options[option->userSetChoice],"Point")==0) {
459                 ((OsdWin*)Osd::getInstance())->setFilterType(D3DTEXF_POINT);
460             } else if (STRCASECMP(option->options[option->userSetChoice],"Linear")==0) {
461                 ((OsdWin*)Osd::getInstance())->setFilterType(D3DTEXF_LINEAR);
462             }
463    return true;
464                 } break;
465         case 2: {
466             if (STRCASECMP(option->options[option->userSetChoice],"NoMix")==0)  {
467                 vmrdeinterlacing=0;
468             } else if (STRCASECMP(option->options[option->userSetChoice],"None")==0)  {
469                 vmrdeinterlacing=1;
470             } else if (STRCASECMP(option->options[option->userSetChoice],"Best")==0)  {
471                 vmrdeinterlacing=2;
472             } else if (STRCASECMP(option->options[option->userSetChoice],"Bob")==0)  {
473                 vmrdeinterlacing=3;
474             } else if (STRCASECMP(option->options[option->userSetChoice],"Weave")==0)  {
475                 vmrdeinterlacing=4;
476             } 
477                 }break;
478                  case 3: {
479             if (STRCASECMP(option->options[option->userSetChoice],"VMR9")==0)  {
480                 currentpresenter=VMR9;
481             } else if (STRCASECMP(option->options[option->userSetChoice],"EVR")==0)  {
482                 currentpresenter=EVR;
483             } 
484                 }break;
485     };
486     return false;
487
488 }
489
490 bool VideoWin::saveOptionstoServer()
491 {
492     if (videofilterselected!=-1) {
493         VDR::getInstance()->configSave("DirectShow",
494             "VideoFilter",videofilterlist[videofilterselected].displayname);
495                  VDR::getInstance()->configSave("DirectShow",
496             "VideoH264Filter",videoH264filterlist[videoH264filterselected].displayname);
497     }
498     return true;
499 }
500
501 /*Option(UINT id, const char* displayText, const char* configSection, const char* configKey, UINT optionType, 
502            UINT numChoices, UINT defaultChoice, UINT startInt,
503            const char * const * options, const char * const * optionkeys = NULL, AbstractOption* handler=NULL);*/
504
505 bool VideoWin::addOptionsToPanes(int panenumber,Options *options,WOptionPane* pane)
506 {
507     if (!Video::addOptionsToPanes(panenumber,options,pane)) return false;
508
509
510     Option* option;
511     if (panenumber == 2) 
512     {
513         DWORD scalingcaps=((OsdWin*)Osd::getInstance())->getFilterCaps();
514         char **scalingopts=new char *[3];
515         int i=0;
516         scalingopts[i]=new char[strlen("None")+1];
517         strcpy(scalingopts[i],"None");
518         i++;
519         if ((scalingcaps & D3DPTFILTERCAPS_MINFPOINT)!=0 
520             && (scalingcaps & D3DPTFILTERCAPS_MAGFPOINT)!=0) {
521             scalingopts[i]=new char[strlen("Point")+1];
522             strcpy(scalingopts[i],"Point");
523             i++;
524         }
525         if ((scalingcaps & D3DPTFILTERCAPS_MINFLINEAR)!=0 
526             && (scalingcaps & D3DPTFILTERCAPS_MAGFLINEAR)!=0) {
527             scalingopts[i]=new char[strlen("Linear")+1];
528             strcpy(scalingopts[i],"Linear");
529             i++;
530         }
531         option = new Option(1 ,tr("Video Stretching Filter"), "DirectGraphics", "StretchFiltering", Option::TYPE_TEXT, i, (i-1), 0, scalingopts,NULL,true, this);
532         options->push_back(option);
533         pane->addOptionLine(option);
534         static const char* deintopts[]={"NoMix","None","Best","Bob","Weave"};
535         option = new Option(2,tr("VMR9 Deinterlacing Mode"), "DirectShow","VMR9DeinterlacingMode",Option::TYPE_TEXT,5,2,0,deintopts,NULL,false,this);
536         options->push_back(option);
537         pane->addOptionLine(option);
538
539                 if (((OsdWin*)Osd::getInstance())->IsEvrSupported()) 
540                 {
541                         static const char* presenteropts[]={"EVR","VMR9"};
542                         option = new Option(3,tr("Video Presenter Filter"),"DirectShow", "VideoPresenter",Option::TYPE_TEXT,2,0,0,presenteropts,NULL,false,this);
543                 } else {
544                         static const char* presenteropts[]={"VMR9"};
545                         option = new Option(3,tr("Video Presenter Filter"),"DirectShow", "VideoPresenter",Option::TYPE_TEXT,1,0,0,presenteropts,NULL,false,this);
546                 }
547                 options->push_back(option);
548         pane->addOptionLine(option);
549
550       
551     }
552
553     return true;
554 }
555
556 IBaseFilter *VideoWin::getVideoFilter()
557 {
558     IBaseFilter *curfilter= NULL;
559     if (videofilterselected == -1)
560     {
561         int i;
562         for (i = 0;i <videofilterlist.size();i++)
563         {
564             
565             if (videofilterlist[i].vmr9tested == true)
566             {
567                 if (videofilterlist[i].vmr9 == true)
568                 {
569                     videofilterselected = i;
570                     break;
571                 } 
572                 else
573                 {
574                     continue;
575                 }
576             }
577             else
578             {
579                 IMoniker * moni=NULL;
580                 IBindCtx *bindctx=NULL;
581                 if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
582                 LPCOLESTR name=(LPCOLESTR)new WCHAR[strlen(videofilterlist[i].displayname)+1];
583                 mbstowcs((wchar_t*)name,videofilterlist[i].displayname,strlen(videofilterlist[i].displayname)+1);
584                 ULONG eater=0;
585                 
586
587                 if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
588                 {
589                     if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
590                     {
591                         IAMDecoderCaps* desccaps=NULL;
592                         if (curfilter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK)
593                         {
594                             DWORD caps;
595                             desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps);
596                             if (caps == DECODER_CAP_SUPPORTED)
597                             {
598                                 videofilterlist[i].vmr9tested =  true;
599                                 videofilterlist[i].vmr9 = true;
600                                 videofilterselected = i;
601                             } 
602                             else
603                             {
604                                 videofilterlist[i].vmr9tested =  true;
605                                 videofilterlist[i].vmr9 = false;
606                                 
607                                 curfilter->Release();
608                                 curfilter=NULL;
609                             }
610                         }
611                         desccaps->Release();
612                     }
613                     moni->Release();
614                 } 
615                 delete [] name;
616                 bindctx->Release();
617             }
618             if (videofilterlist[i].vmr9) break;
619             
620         }
621         if (curfilter != NULL)
622         {
623             VDR *vdr=VDR::getInstance();
624             if (vdr != NULL)
625             {
626                 vdr->configSave("DirectShow","VideoFilter",
627                     videofilterlist[videofilterselected].displayname);
628             }
629             return curfilter;
630         }
631     } 
632     else
633     {
634         IBindCtx *bindctx=NULL;
635         if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
636         IMoniker * moni=NULL;
637         LPCOLESTR name=new WCHAR[strlen(videofilterlist[videofilterselected].displayname)+1];
638         mbstowcs((wchar_t*)name,videofilterlist[videofilterselected].displayname,
639             strlen(videofilterlist[videofilterselected].displayname)+1);
640         ULONG eater;
641         if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
642         {
643             if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
644             {
645                     IAMDecoderCaps* desccaps=NULL;
646                     if (curfilter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK)
647                     {
648                         DWORD caps;
649                         desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps);
650                         if (caps == DECODER_CAP_SUPPORTED)
651                         {
652                             videofilterlist[videofilterselected].vmr9tested =  true;
653                             videofilterlist[videofilterselected].vmr9 = true;
654                         } 
655                         else
656                         {
657                             videofilterlist[videofilterselected].vmr9tested =  true;
658                             videofilterlist[videofilterselected].vmr9 = false;
659                             Log::getInstance()->log("VideoWin", Log::WARN ,"Filter does not support VMR9, but is selected, manual selection!");
660                         }
661                     }
662                     moni->Release();
663                     delete [] name;
664                     bindctx->Release();
665                     return curfilter;
666              } 
667             moni->Release();
668         }
669         bindctx->Release();
670         delete [] name;
671         return NULL;         
672     }
673     return NULL;
674     
675 }
676
677 IBaseFilter *VideoWin::getVideoH264Filter()
678 {
679     IBaseFilter *curfilter= NULL;
680     if (videoH264filterselected == -1)
681     {
682         int i;
683         for (i = 0;i <videoH264filterlist.size();i++)
684         {
685             
686             if (videoH264filterlist[i].vmr9tested == true)
687             {
688                 if (videoH264filterlist[i].vmr9 == true)
689                 {
690                     videoH264filterselected = i;
691                     break;
692                 } 
693                 else
694                 {
695                     continue;
696                 }
697             }
698             else
699             {
700                 IMoniker * moni=NULL;
701                 IBindCtx *bindctx=NULL;
702                 if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
703                 LPCOLESTR name=(LPCOLESTR)new WCHAR[strlen(videoH264filterlist[i].displayname)+1];
704                 mbstowcs((wchar_t*)name,videoH264filterlist[i].displayname,strlen(videoH264filterlist[i].displayname)+1);
705                 ULONG eater=0;
706                                 Log::getInstance()->log("VideoWin", Log::DEBUG ,"Creating filter: %s",videoH264filterlist[i].friendlyname);
707
708                 
709
710                 if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
711                 {
712                     if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
713                     {
714                         IAMDecoderCaps* desccaps=NULL;
715                         if (curfilter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK)
716                         {
717                             DWORD caps;
718                             desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps);
719                             if (caps == DECODER_CAP_SUPPORTED)
720                             {
721                                 videoH264filterlist[i].vmr9tested =  true;
722                                 videoH264filterlist[i].vmr9 = true;
723                                 videoH264filterselected = i;
724                             } 
725                             else
726                             {
727                                 videoH264filterlist[i].vmr9tested =  true;
728                                 videoH264filterlist[i].vmr9 = false;
729                                 
730                                 curfilter->Release();
731                                 curfilter=NULL;
732                             }
733                         }
734                         desccaps->Release();
735                     }
736                     moni->Release();
737                 } 
738                 delete [] name;
739                 bindctx->Release();
740             }
741             if (videoH264filterlist[i].vmr9) break;
742             
743         }
744         if (curfilter != NULL)
745         {
746             VDR *vdr=VDR::getInstance();
747             if (vdr != NULL)
748             {
749                 vdr->configSave("DirectShow","VideoH264Filter",
750                     videoH264filterlist[videoH264filterselected].displayname);
751             }
752             return curfilter;
753         }
754     } 
755     else
756     {
757         IBindCtx *bindctx=NULL;
758         if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
759         IMoniker * moni=NULL;
760         LPCOLESTR name=new WCHAR[strlen(videoH264filterlist[videoH264filterselected].displayname)+1];
761         mbstowcs((wchar_t*)name,videoH264filterlist[videoH264filterselected].displayname,
762             strlen(videoH264filterlist[videoH264filterselected].displayname)+1);
763         ULONG eater;
764                 Log::getInstance()->log("VideoWin", Log::DEBUG ,"Creating filter: %s",videoH264filterlist[videoH264filterselected].friendlyname);
765         if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
766         {
767             if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
768             {
769                     IAMDecoderCaps* desccaps=NULL;
770                     if (curfilter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK)
771                     {
772                         DWORD caps;
773                         desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps);
774                         if (caps == DECODER_CAP_SUPPORTED)
775                         {
776                             videoH264filterlist[videoH264filterselected].vmr9tested =  true;
777                             videoH264filterlist[videoH264filterselected].vmr9 = true;
778                         } 
779                         else
780                         {
781                             videoH264filterlist[videoH264filterselected].vmr9tested =  true;
782                             videoH264filterlist[videoH264filterselected].vmr9 = false;
783                             Log::getInstance()->log("VideoWin", Log::WARN ,"Filter does not support VMR9, but is selected, manual selection!");
784                         }
785                     }
786                     moni->Release();
787                     delete [] name;
788                     bindctx->Release();
789                     return curfilter;
790              } 
791             moni->Release();
792         }
793         bindctx->Release();
794         delete [] name;
795         return NULL;         
796     }
797     return NULL;
798     
799 }
800
801
802 #ifdef DS_DEBUG // This stuff would not included in vomp due to lincemse restrcitions
803 #include "dshelper.h"
804 #endif
805
806 #define DO_VIDEO
807
808 int VideoWin::play()
809 {
810   if (!initted) return 0;
811   return 1;
812 }
813
814 bool VideoWin::addOptionPagesToWTB(WTabBar *wtb)
815 {
816     Boxx *box=new WWinVideoFilter();
817     wtb->addTab(tr("Video Filter"), box);
818         box=new WWinVideoH264Filter();
819     wtb->addTab(tr("H264 Filter"), box);
820     return true;
821 }
822
823 const VideoFilterDescList *VideoWin::getVideoFilterList(int &selected)
824 {
825     selected=videofilterselected;
826     return &videofilterlist;
827 }
828
829 const VideoFilterDescList *VideoWin::getVideoH264FilterList(int &selected)
830 {
831     selected=videoH264filterselected;
832     return &videoH264filterlist;
833 }
834
835 bool VideoWin::selectVideoFilter(int filter)
836 {
837     IBindCtx *bindctx=NULL;
838     if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
839     IMoniker * moni=NULL;
840     LPCOLESTR name=new WCHAR[strlen(videofilterlist[filter].displayname)+1];
841     mbstowcs((wchar_t*)name,videofilterlist[filter].displayname,
842     strlen(videofilterlist[filter].displayname)+1);
843     ULONG eater;
844     bool success=false;
845     if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
846     {
847         IBaseFilter* curfilter=NULL;
848         if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
849         {
850             IAMDecoderCaps* desccaps=NULL;
851             if (curfilter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK)
852             {
853                 DWORD caps;
854                 HRESULT hres=desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps);
855                 if (caps == DECODER_CAP_SUPPORTED)
856                 {
857                     videofilterlist[filter].vmr9tested =  true;
858                     videofilterlist[filter].vmr9 = true;
859                     success=true;
860                 } 
861                 else
862                 {
863                     videofilterlist[filter].vmr9tested =  true;
864                     videofilterlist[filter].vmr9 = false;
865                     success=false;
866                  }
867                 desccaps->Release();
868             } else {
869                 videofilterlist[filter].vmr9tested =  true;
870                 videofilterlist[filter].vmr9 = false;
871                 success=false;
872             }
873
874              curfilter->Release();
875              
876         } 
877         moni->Release();
878     }
879     bindctx->Release();
880     delete [] name;
881     if (success || true) 
882     {
883         videofilterselected=filter;
884         return true;
885     } 
886     else
887     {
888         return false;
889     }
890 }
891
892 bool VideoWin::selectVideoH264Filter(int filter)
893 {
894     IBindCtx *bindctx=NULL;
895     if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
896     IMoniker * moni=NULL;
897     LPCOLESTR name=new WCHAR[strlen(videoH264filterlist[filter].displayname)+1];
898     mbstowcs((wchar_t*)name,videoH264filterlist[filter].displayname,
899     strlen(videoH264filterlist[filter].displayname)+1);
900     ULONG eater;
901     bool success=false;
902     if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
903     {
904         IBaseFilter* curfilter=NULL;
905         if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
906         {
907             IAMDecoderCaps* desccaps=NULL;
908             if (curfilter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK)
909             {
910                 DWORD caps;
911                 HRESULT hres=desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps);
912                 if (caps == DECODER_CAP_SUPPORTED)
913                 {
914                     videoH264filterlist[filter].vmr9tested =  true;
915                     videoH264filterlist[filter].vmr9 = true;
916                     success=true;
917                 } 
918                 else
919                 {
920                     videoH264filterlist[filter].vmr9tested =  true;
921                     videoH264filterlist[filter].vmr9 = false;
922                     success=false;
923                  }
924                 desccaps->Release();
925             } else {
926                 videoH264filterlist[filter].vmr9tested =  true;
927                 videoH264filterlist[filter].vmr9 = false;
928                 success=false;
929             }
930
931              curfilter->Release();
932              
933         } 
934         moni->Release();
935     }
936     bindctx->Release();
937     delete [] name;
938     if (success || true) 
939     {
940         videoH264filterselected=filter;
941         return true;
942     } 
943     else
944     {
945         return false;
946     }
947 }
948
949 int VideoWin::dsInitVideoFilter()
950 {
951     #ifdef DO_VIDEO
952     HRESULT hres;
953     if (videoon) {
954     //We alloc the vmr9 as next step
955                 if (currentpresenter==VMR9) 
956                 {
957                         Log::getInstance()->log("VideoWin", Log::INFO ,"VMR9 Videopresenter selected!");
958                         if (hres=CoCreateInstance(CLSID_VideoMixingRenderer9,0,
959                                 CLSCTX_INPROC_SERVER,IID_IBaseFilter,(void**) &dsrenderer)!=S_OK) 
960                         {
961                                 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed creating VMR9 renderer!");
962                                 ReleaseMutex(filtermutex);
963                                 CleanupDS();
964                         }
965                         /*VMR 9 stuff**/
966                         if (hres=dsgraphbuilder->AddFilter(dsrenderer,L"VMR9")!=S_OK)
967                         {
968                                 ReleaseMutex(filtermutex);
969                                 CleanupDS();
970                                 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed adding VMR9 renderer!");
971                                 return 0;
972                         }
973                         IVMRFilterConfig9* vmrfilconfig;
974                         if (dsrenderer->QueryInterface(IID_IVMRFilterConfig9,(void**)&vmrfilconfig)!=S_OK)
975                         {
976                                 ReleaseMutex(filtermutex);
977                                 CleanupDS();
978                                 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Filterconfig interface!");
979                                 return 0;
980                         }
981                         if (vmrdeinterlacing!=0) vmrfilconfig->SetNumberOfStreams(1);//Enter Mixing Mode
982                         vmrfilconfig->SetRenderingMode(VMR9Mode_Renderless);
983                         vmrfilconfig->Release();
984                         if (dsrenderer->QueryInterface(IID_IVMRSurfaceAllocatorNotify9,
985                                 (void**)& dsvmrsurfnotify) != S_OK)
986                         {
987                                 ReleaseMutex(filtermutex);
988                                 CleanupDS();
989                                 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Surface Allocator interface!");
990                                 return 0;
991                         }
992                         allocatorvmr=new DsAllocator();
993                         dsvmrsurfnotify->AdviseSurfaceAllocator(NULL,allocatorvmr);
994                         allocatorvmr->AdviseNotify(dsvmrsurfnotify);
995                         
996                         IVMRDeinterlaceControl9* deintctrl;
997                         if (dsrenderer->QueryInterface(IID_IVMRDeinterlaceControl9,(void**)&deintctrl)!=S_OK)
998                         {
999                                 ReleaseMutex(filtermutex);
1000                                 CleanupDS();
1001                                 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Deinterlace control!");
1002                                 return 0;
1003                         }
1004                         /*turnoff*/
1005                         switch (vmrdeinterlacing)
1006                         {
1007                         case 1: //No Deinterlasing
1008                          deintctrl->SetDeinterlaceMode(0xFFFFFFFF,(LPGUID)&GUID_NULL);//Turn Off
1009             break;
1010                         case 2: //Best
1011              deintctrl->SetDeinterlacePrefs(DeinterlacePref_NextBest);//Choose Next Best
1012             break;
1013                         case 3: //Bob
1014              deintctrl->SetDeinterlacePrefs(DeinterlacePref_BOB);//Choose NBob
1015                         break;
1016                         case 4: //Weave
1017              deintctrl->SetDeinterlacePrefs(DeinterlacePref_Weave);//Choose Weave
1018              break;
1019                         };
1020                         deintctrl->Release();
1021                         /*VMR 9 stuff end */
1022                 }
1023                 else if (currentpresenter==EVR)
1024                 {
1025                         Log::getInstance()->log("VideoWin", Log::INFO ,"EVR Videopresenter selected!");
1026                         if (hres=CoCreateInstance(CLSID_EnhancedVideoRenderer,0,
1027                                 CLSCTX_INPROC_SERVER,IID_IBaseFilter,(void**) &dsrenderer)!=S_OK) 
1028                         {
1029                                 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed creating EVR renderer!");
1030                                 ReleaseMutex(filtermutex);
1031                                 CleanupDS();
1032                         }
1033                         /*EVR stuff**/
1034                         if (hres=dsgraphbuilder->AddFilter(dsrenderer,L"EVR")!=S_OK)
1035                         {
1036                                 ReleaseMutex(filtermutex);
1037                                 CleanupDS();
1038                                 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed adding EVR renderer!");
1039                                 return 0;
1040                         }
1041                         
1042                         
1043                         IMFGetService *evr_services;
1044                         if (dsrenderer->QueryInterface(IID_IMFGetService,(void**)&evr_services)!=S_OK)
1045                         {
1046                                 ReleaseMutex(filtermutex);
1047                                 CleanupDS();
1048                                 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting EVR IMFGetServices interface!");
1049                                 return 0;
1050                         }
1051
1052                         IMFVideoDisplayControl* mfvideodisplaycontrol;
1053                         if (evr_services->GetService(MR_VIDEO_RENDER_SERVICE,IID_IMFVideoDisplayControl,(void**)&mfvideodisplaycontrol)!=S_OK)
1054                         {
1055                                 ReleaseMutex(filtermutex);
1056                                 CleanupDS();
1057                                 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting EVR IMFVideoDisplayControl interface!");
1058                                 return 0;
1059                         }
1060
1061                         evr_services->Release();
1062                         mfvideodisplaycontrol->SetVideoWindow(((OsdWin*) Osd::getInstance())->getWindow());
1063                         //RECT client;
1064                     //GetClientRect(((OsdWin*) Osd::getInstance())->getWindow(), &client);
1065                         //mfvideodisplaycontrol->SetVideoPosition(NULL,&client);
1066
1067                         mfvideodisplaycontrol->Release();
1068
1069
1070                 ///     if (vmrdeinterlacing!=0) vmrfilconfig->SetNumberOfStreams(1);//Enter Mixing Mode //always the case for evr!
1071
1072                         IMFVideoRenderer *mfvideorenderer;
1073                         if (dsrenderer->QueryInterface(IID_IMFVideoRenderer,(void**)&mfvideorenderer)!=S_OK)
1074                         {
1075                                 ReleaseMutex(filtermutex);
1076                                 CleanupDS();
1077                                 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting EVR IMFVideoRenderer interface!");
1078                                 return 0;
1079                         }
1080                         
1081                         allocatorvmr=new DsAllocator();
1082                         HRESULT hres=mfvideorenderer->InitializeRenderer(NULL,allocatorvmr);
1083
1084                         mfvideorenderer->Release();
1085                         //How should I do this in EVR?
1086                 /*      IVMRDeinterlaceControl9* deintctrl;
1087                         if (dsrenderer->QueryInterface(IID_IVMRDeinterlaceControl9,(void**)&deintctrl)!=S_OK)
1088                         {
1089                                 ReleaseMutex(filtermutex);
1090                                 CleanupDS();
1091                                 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Deinterlace control!");
1092                                 return 0;
1093                         }
1094                         /*turnoff*
1095                         switch (vmrdeinterlacing)
1096                         {
1097                         case 1: //No Deinterlasing
1098                          deintctrl->SetDeinterlaceMode(0xFFFFFFFF,(LPGUID)&GUID_NULL);//Turn Off
1099             break;
1100                         case 2: //Best
1101              deintctrl->SetDeinterlacePrefs(DeinterlacePref_NextBest);//Choose Next Best
1102             break;
1103                         case 3: //Bob
1104              deintctrl->SetDeinterlacePrefs(DeinterlacePref_BOB);//Choose NBob
1105                         break;
1106                         case 4: //Weave
1107              deintctrl->SetDeinterlacePrefs(DeinterlacePref_Weave);//Choose Weave
1108              break;
1109                         };
1110                         deintctrl->Release();*/
1111                         /*EVR stuff end */
1112                 } else {
1113                         Log::getInstance()->log("VideoWin", Log::ERR ,"No videopresenter selected! Please post on the forum!");
1114                         return -1;
1115                 }
1116         IFilterGraph2*fg2=NULL;
1117         if (dsgraphbuilder->QueryInterface(IID_IFilterGraph2,(void**)&fg2)!= S_OK)
1118         {
1119             Log::getInstance()->log("VideoWin", Log::WARN , "Failed querying for FilterGraph2 Interface!");
1120             ReleaseMutex(filtermutex);
1121                 CleanupDS();
1122             return 0;
1123         }
1124 /*#ifndef NEW_DS_MECHANISMENS
1125         
1126         if (hres=fg2->RenderEx((IPin*)sourcefilter->GetVideoPin()/*video*,
1127             AM_RENDEREX_RENDERTOEXISTINGRENDERERS,NULL) != S_OK) 
1128         {
1129             Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering Video!");
1130                 fg2->Release();
1131                 ReleaseMutex(filtermutex);
1132                 CleanupDS();
1133             return 0;
1134         }
1135         
1136 #else*/
1137         IBaseFilter*videofilter;
1138                 if (h264)  
1139                 {
1140                         Log::getInstance()->log("VideoWin", Log::DEBUG ,"Entering h264 playback...");
1141                         videofilter=getVideoH264Filter();
1142                 } 
1143                 else
1144                 {
1145                         Log::getInstance()->log("VideoWin", Log::DEBUG ,"Entering MPEG2 playback...");
1146                         videofilter=getVideoFilter();
1147                 }
1148         if (hres=dsgraphbuilder->AddFilter(videofilter,NULL) != S_OK) 
1149         {
1150             Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Video Filter!");
1151             ReleaseMutex(filtermutex);
1152             CleanupDS();
1153             return 0;
1154         }
1155         IEnumPins *pinenum=NULL;
1156         bool error=false;
1157
1158         mptype_video_detail vid_details;
1159         Demuxer* demux=Demuxer::getInstance();
1160         vid_details.width=demux->getHorizontalSize();
1161         vid_details.height=demux->getVerticalSize();
1162
1163                 if (h264)
1164                 {
1165                         sourcefilter->GetVideoPin()->SetPinMode(MPTYPE_VIDEO_H264,&vid_details);
1166                 }
1167                 else
1168                 {
1169                         sourcefilter->GetVideoPin()->SetPinMode(MPTYPE_VIDEO_MPEG2,&vid_details);
1170                 }
1171         if (videofilter->EnumPins(&pinenum) == S_OK)
1172         {
1173             IPin *current=NULL;
1174             ULONG fetch=0;
1175             bool firststep=false;
1176
1177             while (pinenum->Next(1,&current,&fetch)==S_OK)
1178             {
1179                 PIN_DIRECTION dir;
1180                 if (current->QueryDirection(&dir)==S_OK)
1181                 {
1182                     if (dir == PINDIR_INPUT)
1183                     {
1184                         if (sourcefilter->GetVideoPin()->Connect(current,NULL)==S_OK)
1185                         {
1186                             current->Release();
1187                             firststep=true;
1188                             break;
1189                         }
1190                     }
1191                 }
1192                 current->Release();
1193             }
1194             if (firststep==false)
1195             {
1196                 Log::getInstance()->log("VideoWin", Log::WARN , "Video Filter has no suitable input!");
1197                 videofilter->Release();
1198                 ReleaseMutex(filtermutex);
1199                 CleanupDS();
1200                 return 0;
1201             }
1202             bool secondstep=false;
1203             pinenum->Reset();
1204             while (pinenum->Next(1,&current,&fetch)==S_OK)
1205             {
1206                 PIN_DIRECTION dir;
1207                 if (current->QueryDirection(&dir)==S_OK)
1208                 {
1209                     if (dir == PINDIR_OUTPUT)
1210                     {
1211                         
1212                         if (fg2->RenderEx((IPin*)current/*video*/,
1213                                 AM_RENDEREX_RENDERTOEXISTINGRENDERERS,NULL) ==S_OK)
1214                         {
1215                             current->Release();
1216                             secondstep=true;
1217                             break;
1218                         }
1219                     }
1220                 }
1221                 current->Release();
1222             }
1223             if (secondstep==false)
1224             {
1225                 Log::getInstance()->log("VideoWin", Log::WARN , "Video Filter has no suitable output!");
1226                 videofilter->Release();
1227                 ReleaseMutex(filtermutex);
1228                 CleanupDS();
1229                 return 0;
1230             }
1231             
1232             videofilter->Release();
1233             pinenum->Release();
1234
1235         }
1236
1237
1238
1239         fg2->Release();
1240         return 1;
1241     }
1242 #endif 
1243         return 1;
1244 }
1245
1246 int VideoWin::setAudioStreamType(UCHAR type)
1247 {
1248   aud_type=type;
1249   if (!initted) return 0;
1250   return 1;
1251 }
1252
1253 int VideoWin::dsplay()
1254 {
1255     if (!initted) return 0;
1256     CleanupDS();
1257     
1258     //Build filter graph
1259     HRESULT hres;
1260     //So this is the real code, this prevents the feeder from calling noexisting objects!
1261     WaitForSingleObject(filtermutex,INFINITE);
1262     if (hres=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,
1263         IID_IGraphBuilder,(void**)&dsgraphbuilder) != S_OK) 
1264     {
1265         ReleaseMutex(filtermutex);
1266         return 0;
1267     }
1268    #ifdef DS_DEBUG
1269    AddToRot(dsgraphbuilder,&graphidentifier);
1270    #endif
1271    
1272    firstsynched=false;
1273    if (aud_type==Audio::MP3) {
1274        lastaudiomode=MPTYPE_MPEG_AUDIO_LAYER3;
1275    } else {
1276        lastaudiomode=MPTYPE_MPEG_AUDIO;
1277    }
1278    //lastaudiomode=MPTYPE_AC3;
1279    sourcefilter=new DsSourceFilter(); //Creating our Source filter for pushing Data
1280    // to DirectShow
1281    if (hres=dsgraphbuilder->AddFilter(sourcefilter,L"Vomp Win Source Filter") != S_OK) 
1282    {
1283        Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Vomp Source Filter!");
1284        ReleaseMutex(filtermutex);
1285        CleanupDS();
1286        return 0;
1287    }
1288    sourcefilter->GetAudioPin()->SetPinMode(lastaudiomode);
1289    /*if (hres=dsgraphbuilder->Render((IPin*)sourcefilter->GetAudioPin()/*audio*)!=S_OK) 
1290    {
1291        Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering audio!");
1292            ReleaseMutex(filtermutex);
1293        CleanupDS();
1294        return 0;
1295    }*/
1296    if (((AudioWin*)Audio::getInstance())->dsInitAudioFilter(dsgraphbuilder)==0)
1297    {
1298        Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering audio!");
1299            ReleaseMutex(filtermutex);
1300        CleanupDS();
1301        return 0;
1302    }
1303
1304
1305     if (dsInitVideoFilter()==0)
1306     { 
1307         return 0;
1308     }
1309
1310     if (hres=CoCreateInstance(CLSID_SystemClock,NULL,CLSCTX_INPROC_SERVER,
1311         IID_IReferenceClock,(void**)&dsrefclock)!=S_OK) 
1312     {
1313         return 0;
1314     }
1315     dsgraphbuilder->QueryInterface(IID_IMediaFilter,(void **) &dsmediafilter);
1316     HRESULT hresdeb = dsmediafilter->SetSyncSource(dsrefclock);
1317
1318     dsgraphbuilder->QueryInterface(IID_IMediaControl,(void **) &dsmediacontrol);
1319     dsgraphbuilder->QueryInterface(IID_IBasicAudio,(void **) &dsbasicaudio);    
1320     if (dsbasicaudio) 
1321        dsbasicaudio->put_Volume(audiovolume);
1322     dsinited=true;
1323    //MILLISLEEP(100);
1324
1325     hresdeb=dsmediacontrol->Run();
1326     iframemode=false;//exit iframe mode
1327     ReleaseMutex(filtermutex);
1328     return 1;
1329 }
1330
1331 int VideoWin::EnterIframePlayback()
1332 {
1333         if (!initted) return 0;
1334         CleanupDS();
1335         //So this is the real code, this prevents the feeder from calling noexisting objects!
1336    WaitForSingleObject(filtermutex,INFINITE);
1337         iframemode=true;//enter iframe mode
1338         //Build filter graph
1339         HRESULT hres;
1340         if (hres=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,
1341                  IID_IGraphBuilder,(void**)&dsgraphbuilder)!=S_OK) {
1342                          ReleaseMutex(filtermutex);
1343                          return 0;
1344         }
1345 #ifdef DS_DEBUG
1346         AddToRot(dsgraphbuilder,&graphidentifier);
1347 #endif
1348    
1349    //firstsynched=false;
1350    sourcefilter=new DsSourceFilter(); //Creating our Source filter for pushing Data
1351    // to DirectShow
1352    if (hres=dsgraphbuilder->AddFilter(sourcefilter,L"Vomp Win Source Filter")!=S_OK) {
1353    Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Vomp Source Filter!");
1354      ReleaseMutex(filtermutex);  
1355      CleanupDS();
1356      return 0;
1357    }
1358 #ifdef DO_VIDEO
1359     if (videoon) {
1360         dsInitVideoFilter();
1361    }
1362 #endif
1363 /*   if (hres=CoCreateInstance(CLSID_SystemClock,NULL,CLSCTX_INPROC_SERVER,
1364     IID_IReferenceClock,(void**)&dsrefclock)!=S_OK) {
1365       return 0;
1366    }*/
1367
1368    dsgraphbuilder->QueryInterface(IID_IMediaFilter,(void **) &dsmediafilter);
1369    dsmediafilter->SetSyncSource(/*dsrefclock*/NULL); //Run as fast as you can!
1370
1371    dsgraphbuilder->QueryInterface(IID_IMediaControl,(void **) &dsmediacontrol);
1372    dsgraphbuilder->QueryInterface(IID_IBasicAudio,(void **) &dsbasicaudio);     
1373   dsinited=true;
1374   
1375
1376    dsmediacontrol->Run();
1377    ReleaseMutex(filtermutex);
1378   return 1;
1379
1380 }
1381
1382 int VideoWin::dsstop()
1383 {
1384   if (!initted) return 0;
1385
1386   CleanupDS();
1387
1388
1389   return 1;
1390 }
1391
1392 int VideoWin::stop()
1393 {
1394   if (!initted) return 0;
1395
1396
1397   return 1;
1398 }
1399
1400 int VideoWin::reset()
1401 {
1402   if (!initted) return 0;
1403   
1404
1405   return 1;
1406 }
1407
1408 int VideoWin::dsreset()
1409 {
1410   if (!initted) return 0;
1411   videoposx=0;
1412   videoposy=0;
1413   iframemode=false;//exit iframe mode
1414   CleanupDS();
1415
1416   return 1;
1417 }
1418
1419 int VideoWin::dspause()
1420 {
1421   if (!initted) return 0;
1422   WaitForSingleObject(filtermutex,INFINITE);
1423   if (dsmediacontrol) dsmediacontrol->Pause();
1424   ReleaseMutex(filtermutex);
1425   return 1;
1426 }
1427
1428 int VideoWin::pause()
1429 {
1430   if (!initted) return 0;
1431   
1432   return 1;
1433 }
1434
1435 int VideoWin::unPause() // FIXME get rid - same as play!!
1436 {//No on windows this is not the same, I don't get rid of!
1437   if (!initted) return 0;
1438   return 1;
1439 }
1440
1441 int VideoWin::dsunPause() // FIXME get rid - same as play!!
1442 {//No on windows this is not the same, I don't get rid of!
1443   if (!initted) return 0;
1444   WaitForSingleObject(filtermutex,INFINITE);
1445   if (dsmediacontrol) dsmediacontrol->Run();
1446   ReleaseMutex(filtermutex);
1447
1448   return 1;
1449 }
1450
1451 int VideoWin::fastForward()
1452 {
1453   if (!initted) return 0;
1454
1455   return 1;
1456 }
1457
1458 int VideoWin::unFastForward()
1459 {
1460   if (!initted) return 0;
1461   
1462   return 1;
1463 }
1464
1465 int VideoWin::attachFrameBuffer()
1466 {
1467   if (!initted) return 0;
1468   return 1;
1469 }
1470
1471 int VideoWin::blank(void)
1472 {
1473   ((OsdWin*)Osd::getInstance())->Blank();
1474   return 1;
1475 }
1476
1477 ULLONG VideoWin::getCurrentTimestamp()
1478 {
1479         REFERENCE_TIME startoffset;
1480         REFERENCE_TIME ncr_time;
1481   if (iframemode) return 0; //Not in iframe mode!
1482   if (!dsrefclock || !sourcefilter) return 0;
1483         FILTER_STATE state;
1484         sourcefilter->GetState(10,&state);
1485
1486         if (state==State_Running) dsrefclock->GetTime(&cr_time);
1487         ncr_time=cr_time;
1488   startoffset=sourcefilter->getStartOffset();
1489         ncr_time-=startoffset;
1490         ncr_time-=lastreftimeRT;
1491  /* ULLONG result=frameNumberToTimecode(
1492     VDR::getInstance()->frameNumberFromPosition(lastreftimeBYTE));*/
1493         ULLONG result=lastreftimePTS;
1494         result+=(ULLONG)(ncr_time/10000LL*90LL);
1495   return result;
1496
1497 }
1498 /* //to beremoved
1499 ULONG VideoWin::timecodeToFrameNumber(ULLONG timecode)
1500 {
1501   if (format == PAL) return (ULONG)(((double)timecode / (double)90000) * (double)25);
1502   else               return (ULONG)(((double)timecode / (double)90000) * (double)30);
1503 }
1504
1505 ULLONG VideoWin::frameNumberToTimecode(ULONG framenumber)
1506 {
1507   if (format == PAL) return (ULLONG)(((double)framenumber * (double)90000) / (double)25);
1508   else               return (ULLONG)(((double)framenumber * (double)90000) / (double)30);
1509 }
1510 */
1511 void VideoWin::CleanupDS()
1512 {
1513   WaitForSingleObject(filtermutex,INFINITE);
1514   dsinited=false;
1515   if (dsmediacontrol)dsmediacontrol->Stop();
1516   if (cur_audio_media_sample) {
1517     cur_audio_media_sample->Release();
1518     cur_audio_media_sample=NULL;
1519   }
1520   if (cur_video_media_sample) {
1521     cur_video_media_sample->Release();
1522     cur_video_media_sample=NULL;
1523   }
1524   if (dsbasicaudio) {
1525           dsbasicaudio->Release();
1526           dsbasicaudio=NULL;
1527   }
1528   if (dsvmrsurfnotify) {
1529     dsvmrsurfnotify->Release();
1530     dsvmrsurfnotify=NULL;
1531   }
1532   if (dsrenderer) {
1533     dsrenderer->Release();
1534     dsrenderer=NULL;
1535   }
1536
1537   if (allocatorvmr) {
1538     allocatorvmr->Release();
1539     allocatorvmr=NULL;
1540   }
1541
1542   if (dsrefclock) {
1543     dsrefclock->Release();
1544     dsrefclock=NULL;
1545   }
1546   if (dsmediafilter) {
1547     dsmediafilter->Release();
1548     dsmediafilter=NULL;
1549   }
1550
1551
1552
1553   if (dsmediacontrol) {
1554     dsmediacontrol->Stop();
1555     dsmediacontrol->Release();
1556     dsmediacontrol=NULL;
1557   }
1558   if (dsgraphbuilder){
1559 #ifdef DS_DEBUG
1560     RemoveFromRot(graphidentifier);
1561 #endif
1562         dsgraphbuilder->Release();
1563     dsgraphbuilder=NULL;
1564         
1565     sourcefilter=NULL; //The Graph Builder destroys our SourceFilter
1566   }
1567   ReleaseMutex(filtermutex);
1568
1569 }
1570
1571 void VideoWin::PrepareMediaSample(const MediaPacketList& mplist,
1572      UINT samplepos)
1573 {
1574   mediapacket = mplist.front();
1575 }
1576
1577 UINT VideoWin::DeliverMediaSample(UCHAR* buffer, UINT *samplepos)
1578 {
1579   DeliverMediaPacket(mediapacket, buffer, samplepos);
1580   if (*samplepos == mediapacket.length) {
1581     *samplepos = 0;
1582     return 1;
1583   }
1584   else return 0;
1585 }
1586
1587 UINT VideoWin::DeliverMediaPacket(MediaPacket packet,
1588                                   const UCHAR* buffer,
1589                                   UINT *samplepos)
1590 {
1591
1592     /*First Check, if we have an audio sample*/
1593     if (!isdsinited()) return 0;
1594     if (packet.type == MPTYPE_VIDEO_H264)
1595     {
1596         h264=true;
1597     }
1598     else
1599     {
1600         h264=false;
1601     }
1602
1603 #ifdef DO_VIDEO
1604     if (!videoon) {
1605         *samplepos+=packet.length;
1606         MILLISLEEP(0); //yet not implemented//bad idea
1607         return packet.length;
1608     }
1609     /*First Check, if we have an audio sample*/
1610     if (iframemode) {
1611         //samplepos=0;
1612         MILLISLEEP(10);
1613         return 0; //Not in iframe mode!
1614     }
1615     IMediaSample* ms=NULL;
1616     REFERENCE_TIME reftime1=0;
1617     REFERENCE_TIME reftime2=0;
1618
1619     UINT headerstrip=0;
1620     if (packet.disconti) {
1621         firstsynched=false;
1622         DeliverVideoMediaSample();
1623     }
1624
1625     
1626
1627     /*Inspect PES-Header */
1628
1629     if (*samplepos==0) {//stripheader
1630         headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/;
1631         *samplepos+=headerstrip;
1632         if ( packet.synched ) {
1633             DeliverVideoMediaSample();//write out old data
1634             /*   if (packet.presentation_time<0) { //Preroll?
1635             *samplepos=packet.length;//if we have not processed at least one
1636             return packet.length;//synched packet ignore it!
1637             }*/
1638
1639             reftime1=packet.presentation_time;
1640             reftime2=reftime1+1;
1641             firstsynched=true;
1642         } else {
1643             if (!firstsynched) {//
1644                 *samplepos=packet.length;//if we have not processed at least one
1645                 return packet.length;//synched packet ignore it!
1646             }
1647         }
1648     }
1649     BYTE *ms_buf;
1650     UINT ms_length;
1651     UINT ms_pos;
1652     UINT haveToCopy;
1653
1654     if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
1655         //samplepos=0;
1656         //MessageBox(0,"da isser","hei",0);
1657         //MILLISLEEP(1);
1658         return 0;
1659     }
1660     ms_pos=ms->GetActualDataLength();
1661     ms_length=ms->GetSize();
1662     haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);
1663     if ((ms_length-ms_pos)<1 ) {
1664         DeliverVideoMediaSample(); //we are full!
1665         if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
1666             //samplepos=0;
1667             //MessageBox(0,"da isser","hei",0);
1668             //MILLISLEEP(10);
1669             return 0;
1670         }
1671         ms_pos=ms->GetActualDataLength();
1672         ms_length=ms->GetSize();
1673         haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);
1674     }
1675     ms->GetPointer(&ms_buf);
1676
1677
1678     if (ms_pos==0) {//will only be changed on first packet
1679         if (packet.disconti) {
1680             ms->SetDiscontinuity(TRUE);
1681         } else {
1682             ms->SetDiscontinuity(FALSE);
1683         }
1684         if (packet.synched) {
1685             ms->SetSyncPoint(TRUE);
1686             ms->SetTime(&reftime1,&reftime2);
1687             //Log::getInstance()->log("VideoWin", Log::DEBUG , "Setted videotime to %lld %lld",reftime1,reftime2);
1688             //Log::getInstance()->log("VideoWin", Log::DEBUG , "Packet pts %lld dts %lld",packet.pts,packet.dts);
1689             //ms->SetTime(NULL,NULL);
1690             ms->SetMediaTime(NULL, NULL);
1691             if (reftime1<0) ms->SetPreroll(TRUE);
1692             else ms->SetPreroll(FALSE);
1693             /*Timecode handling*/
1694             lastreftimeRT=reftime1;
1695             lastreftimePTS=packet.pts;
1696
1697         }
1698         else
1699         {
1700             ms->SetSyncPoint(FALSE);
1701             ms->SetTime(NULL,NULL);
1702             ms->SetMediaTime(NULL, NULL);
1703             ms->SetPreroll(FALSE);
1704
1705             //  ms->SetSyncPoint(TRUE);
1706         }
1707     }
1708     
1709
1710
1711     memcpy(ms_buf+ms_pos,buffer+packet.pos_buffer+*samplepos,haveToCopy);
1712     ms->SetActualDataLength(haveToCopy+ms_pos);
1713
1714     *samplepos+=haveToCopy;
1715
1716     return haveToCopy+headerstrip;
1717
1718 #else
1719
1720     *samplepos+=packet.length;
1721     MILLISLEEP(0); //yet not implemented//bad idea
1722     return packet.length;
1723 #endif
1724 }
1725
1726 int VideoWin::getCurrentAudioMediaSample(IMediaSample** ms)
1727 {
1728   //WaitForSingleObject(filtermutex,INFINITE);
1729   if (!sourcefilter){
1730   //  ReleaseMutex(filtermutex);
1731     return 0;
1732   }
1733   if (cur_audio_media_sample) {
1734     *ms=cur_audio_media_sample;//already open
1735     return 1;
1736   }
1737   if (!sourcefilter->getCurrentAudioMediaSample(ms)) {
1738   //  ReleaseMutex(filtermutex);
1739   }
1740   if (*ms) (*ms)->SetActualDataLength(0);
1741   cur_audio_media_sample=*ms;
1742   //Don't release the mutex before deliver
1743   return 1;
1744 }
1745
1746 int VideoWin::getCurrentVideoMediaSample(IMediaSample** ms)
1747 {
1748   //WaitForSingleObject(filtermutex,INFINITE);
1749   if (!sourcefilter){
1750   //  ReleaseMutex(filtermutex);
1751     return 0;
1752   }
1753   if (cur_video_media_sample) {
1754     *ms=cur_video_media_sample;//already open
1755     return 1;
1756   }
1757   if (!sourcefilter->getCurrentVideoMediaSample(ms)) {
1758   //  ReleaseMutex(filtermutex);
1759   }
1760   if (*ms) (*ms)->SetActualDataLength(0);
1761
1762   cur_video_media_sample=*ms;
1763   //Don't release the mutex before deliver
1764   return 1;
1765 }
1766
1767 int VideoWin::DeliverAudioMediaSample(){
1768   if (cur_audio_media_sample) {
1769     sourcefilter->DeliverAudioMediaSample(cur_audio_media_sample);
1770     cur_audio_media_sample=NULL;
1771   }
1772   //ReleaseMutex(filtermutex);
1773   return 1;
1774 }
1775
1776 int VideoWin::DeliverVideoMediaSample(){
1777   if (cur_video_media_sample) {
1778     sourcefilter->DeliverVideoMediaSample(cur_video_media_sample);
1779     cur_video_media_sample=NULL;
1780   }
1781   //ReleaseMutex(filtermutex);
1782   return 1;
1783 }
1784
1785 long long VideoWin::SetStartOffset(long long curreftime, bool *rsync)
1786 {
1787   *rsync=false;
1788   if (offsetnotset) {
1789     startoffset=curreftime;//offset is set for audio
1790     offsetnotset=false;
1791     offsetvideonotset=false;
1792
1793
1794   } else {
1795     if (offsetvideonotset) {
1796       offsetvideonotset=false;
1797       *rsync=true;
1798     } else {
1799       if ( (curreftime-lastrefvideotime)>10000000LL
1800         || (curreftime-lastrefvideotime)<-10000000LL) {//if pts jumps to big resync
1801         startoffset+=curreftime-lastrefvideotime;
1802         lastrefaudiotime+=curreftime-lastrefvideotime;
1803         //*rsync=true;
1804         offsetaudionotset=true;
1805
1806       }
1807     }
1808
1809   }
1810
1811   lastrefvideotime=curreftime;
1812   
1813   return startoffset;
1814
1815 }
1816
1817 long long VideoWin::SetStartAudioOffset(long long curreftime, bool *rsync)
1818 {
1819   *rsync=false;
1820   if (offsetnotset) {
1821     startoffset=curreftime;
1822     offsetnotset=false;
1823     offsetaudionotset=false;
1824   }else {
1825     if (offsetaudionotset) {
1826       offsetaudionotset=false;
1827       *rsync=true;
1828     } else {
1829       if ( (curreftime-lastrefaudiotime)>10000000LL
1830         || (curreftime-lastrefaudiotime)<-10000000LL) {//if pts jumps to big resync
1831         startoffset+=curreftime-lastrefaudiotime;
1832         lastrefvideotime+=curreftime-lastrefaudiotime;
1833         //*rsync=true;
1834         offsetvideonotset=true;
1835
1836       }
1837     }
1838
1839   }
1840   lastrefaudiotime=curreftime;
1841   return startoffset;
1842
1843 }
1844 void VideoWin::ResetTimeOffsets() {
1845   offsetnotset=true; //called from demuxer
1846   offsetvideonotset=true;
1847   offsetaudionotset=true;
1848   startoffset=0;
1849   lastrefaudiotime=0;
1850   lastrefvideotime=0;
1851   lastreftimeRT=0;
1852   lastreftimePTS=0;
1853
1854
1855 }
1856
1857 void VideoWin::SetAudioVolume(long volume)
1858 {
1859     audiovolume=volume;
1860         if (dsbasicaudio) dsbasicaudio->put_Volume(volume);
1861 }
1862
1863 void VideoWin::displayIFrame(const UCHAR* buffer, UINT length)
1864 {
1865         if (!iframemode) EnterIframePlayback();
1866         if (!isdsinited()) return ;
1867         
1868 #ifdef DO_VIDEO
1869   IMediaSample* ms=NULL;
1870   REFERENCE_TIME reftime1=0;
1871   REFERENCE_TIME reftime2=0;
1872   if (!videoon) return;
1873   if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
1874     MILLISLEEP(10);
1875     return ;
1876   }
1877   BYTE *ms_buf;
1878   DWORD ms_length;
1879   ms->GetPointer(&ms_buf);
1880   ms_length=ms->GetSize();
1881   
1882   /*First Check, if we have an video sample*/
1883   DWORD read_pos = 0, write_pos = 0;
1884   DWORD pattern, packet_length;
1885   DWORD headerstrip=0;
1886   bool first=true;
1887   if (length < 4) return ;
1888   //Now we strip the pes header
1889   pattern = (buffer[0] << 16) | (buffer[1] << 8) | (buffer[2]);
1890   while (read_pos + 7 <= length)
1891   {
1892     pattern = ((pattern << 8) & 0xFFFFFFFF) | buffer[read_pos+3];
1893     if (pattern < 0x000001E0 || pattern > 0x000001EF) {
1894       read_pos++;
1895       continue;
1896     }
1897     else
1898     {
1899           headerstrip=buffer[read_pos+8]+9/*is this right*/;
1900       packet_length = ((buffer[read_pos+4] << 8) | (buffer[read_pos+5])) + 6;
1901       if (read_pos + packet_length > length)
1902         read_pos = length;
1903       else
1904       {
1905                   if ( (headerstrip < packet_length) &&
1906               (write_pos+packet_length-headerstrip)>ms_length) {
1907                           if (first) {
1908                   ms->SetSyncPoint(TRUE);
1909                   ms->SetDiscontinuity(TRUE);
1910                   first=false;
1911               } else ms->SetSyncPoint(FALSE);
1912                           ms->SetTime(NULL,NULL);
1913                           ms->SetMediaTime(NULL, NULL);
1914                           ms->SetActualDataLength(write_pos);
1915                           DeliverVideoMediaSample();
1916
1917                           if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
1918                                 MILLISLEEP(10);
1919                                 return ;
1920                           }
1921                           write_pos=0;
1922                           ms_length=ms->GetSize();
1923                           ms->GetPointer(&ms_buf);
1924                   }
1925                   if (packet_length>headerstrip) {
1926                         memcpy(ms_buf+write_pos, buffer+read_pos+headerstrip, packet_length-headerstrip);
1927                         write_pos += packet_length-headerstrip;
1928                   }
1929                   read_pos += packet_length;
1930                   
1931                   pattern = (buffer[read_pos] << 16) | (buffer[read_pos+1] << 8)
1932                                         | (buffer[read_pos+2]);
1933       }
1934     }
1935   }
1936  
1937   if (first) {ms->SetSyncPoint(TRUE);
1938   ms->SetDiscontinuity(TRUE);
1939   first=false;} 
1940   else ms->SetSyncPoint(FALSE);
1941   ms->SetTime(NULL,NULL);
1942   ms->SetMediaTime(NULL, NULL);
1943   ms->SetActualDataLength(write_pos);
1944   DeliverVideoMediaSample();
1945
1946 #else
1947
1948     //   *samplepos+=packet.length;
1949       MILLISLEEP(0); //yet not implemented//bad idea
1950        return ;
1951 #endif
1952 }
1953
1954 bool VideoWin::supportsAc3(){
1955     if (sourcefilter != NULL) {
1956         return sourcefilter->supportsAc3();
1957     } else {
1958         return false;
1959     }
1960 }
1961
1962 bool VideoWin::supportsh264()
1963 {
1964         if (videoH264filterlist.size()>0) return true;
1965         else return false;
1966 }
1967
1968
1969 bool VideoWin::changeAType(int type,IMediaSample* ms){
1970     if (sourcefilter!= NULL) {
1971         lastaudiomode=type;
1972         return sourcefilter->changeAType(type,ms);
1973     }
1974     else 
1975     {
1976         return false;
1977     }
1978 }
1979
1980 #ifdef DEV
1981 int VideoWin::test()
1982 {
1983   return 0;
1984 }
1985
1986 int VideoWin::test2()
1987 {
1988   return 0;
1989 }
1990 #endif
1991
1992
1993
1994