]> git.vomp.tv Git - vompclient.git/blob - videowin.cc
German updates
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 #include "videowin.h"
22 #include "log.h"
23 #include "dssourcefilter.h"
24 #include "dsallocator.h"
25 #include "vdr.h"
26 #include "osdwin.h"
27 #include "audiowin.h"
28 #include "wwinvideofilter.h"
29 #include "wtabbar.h"
30 #include "i18n.h"
31
32 void AdjustWindow();
33
34
35
36 VideoWin::VideoWin()
37 {
38   dsinited=false;
39   dsgraphbuilder=NULL;
40   dsmediacontrol=NULL;
41   dsvmrrenderer=NULL;
42   dsrefclock=NULL;
43   dsmediafilter=NULL;
44   dsbasicaudio=NULL;
45   sourcefilter=NULL;
46   allocatorvmr=NULL;
47   cr_time=0;
48   lastaudiomode=MPTYPE_MPEG_AUDIO;
49   //lastaudiomode=MPTYPE_AC3;
50   dsvmrsurfnotify=NULL;
51   filtermutex=CreateMutex(NULL,FALSE,NULL);
52   offsetnotset=true;
53   offsetvideonotset=true;
54   offsetaudionotset=true;
55   startoffset=0;
56   lastrefaudiotime=0;
57   lastrefvideotime=0;
58   lastreftimeRT=0;
59   lastreftimePTS=0;
60   firstsynched=false;
61   cur_audio_media_sample=NULL;
62   cur_video_media_sample=NULL;
63   videoon=true;
64   audioon=true;
65   audiovolume=0;
66   pseudotvsize=0;
67   videoposx=0;
68   videoposy=0;
69   aud_type=Audio::MPEG2_PES;
70   iframemode=false;//We are not in Iframe mode at begining
71
72   videofilterselected=-1;
73
74
75
76
77 }
78
79 VideoWin::~VideoWin()
80 {
81   CleanupDS();
82   CloseHandle(filtermutex);
83   int i;
84   for (i=0;i<videofilterlist.size();i++)
85   {
86    if (videofilterlist[i].displayname) delete [] videofilterlist[i].displayname;
87    if (videofilterlist[i].friendlyname) delete [] videofilterlist[i].friendlyname;
88   }
89   videofilterlist.clear();
90
91
92
93
94   instance = NULL;
95 }
96
97 int VideoWin::init(UCHAR tformat)
98 {
99   if (initted) return 0;
100
101   initted = 1;
102   tvsize=Video::ASPECT16X9; //Internally Vomp should think we are a 16:9 TV
103   videoposx=0;
104   videoposy=0;
105   initFilterDatabase();
106
107   if (!setFormat(tformat)){ shutdown(); return 0; }
108   return 1;
109 }
110
111
112
113 int VideoWin::setTVsize(UCHAR ttvsize)
114 {
115   pseudotvsize=ttvsize;
116   return 1;
117 }
118
119 int VideoWin::setDefaultAspect()
120 {
121   return setAspectRatio(Video::ASPECT4X3);
122 }
123
124 int VideoWin::shutdown()
125 {
126   if (!initted) return 0;
127   initted = 0;
128   return 1;
129 }
130
131 int VideoWin::setFormat(UCHAR tformat)
132 {
133   if (!initted) return 0;
134   if ((tformat != PAL) && (tformat != NTSC)) return 0;
135   format = tformat;
136   if (format == NTSC)
137   {
138     screenWidth = 720;
139     screenHeight = 480;
140   }
141   if (format == PAL)
142   {
143     screenWidth = 720;
144     screenHeight = 576;
145   }
146
147   return 1;
148 }
149
150 int VideoWin::setConnection(UCHAR tconnection)
151 {
152   if (!initted) return 0;
153   if ((tconnection != COMPOSITERGB) && (tconnection != SVIDEO)) return 0;
154   connection = tconnection;
155
156   return 1;
157 }
158
159 int VideoWin::setAspectRatio(UCHAR taspectRatio)
160 {
161   if (!initted) return 0;
162   if ((taspectRatio != ASPECT4X3) && (taspectRatio != ASPECT16X9)) return 0;
163   aspectRatio = taspectRatio;
164   AdjustWindow();
165   return 1;
166 }
167
168 int VideoWin::setMode(UCHAR tmode)
169 {
170   if (!initted) return 0;
171
172   //if ((tmode == LETTERBOX) && (tvsize == ASPECT16X9)) return 0; // invalid mode
173
174   if ((tmode != NORMAL) && (tmode != LETTERBOX) && (tmode != UNKNOWN2) && (tmode != QUARTER) && (tmode != EIGHTH)
175       && (tmode != ZOOM) && (tmode != UNKNOWN6)) return 0;
176   mode = tmode;
177   videoposx=0;
178   videoposy=0;
179   AdjustWindow();
180
181   return 1;
182 }
183
184 int VideoWin::signalOff()
185 {
186   return 1;
187 }
188
189 int VideoWin::signalOn()
190 {
191   return 1;
192 }
193
194 int VideoWin::setSource()
195 {
196   if (!initted) return 0;
197
198   return 1;
199 }
200
201 int VideoWin::setPosition(int x, int y)
202 {
203   if (!initted) return 0;
204   if (mode==QUARTER || mode==EIGHTH) {
205   videoposx=x;
206   videoposy=y;
207   }
208   return 1;
209 }
210
211 int VideoWin::sync()
212 {
213   if (!initted) return 0;
214
215   return 1;
216 }
217 void VideoWin::initFilterDatabase()
218 {
219     /* This method should determine all availiable DirectShow Filters */
220     IFilterMapper2* filtmap=NULL;
221     HRESULT result;
222     result = CoCreateInstance(CLSID_FilterMapper2,NULL,CLSCTX_INPROC,
223                 IID_IFilterMapper2,(void**)&filtmap);
224     if (result != S_OK)
225     {
226         Log::getInstance()->log("VideoWin", Log::ERR , "Unable to create FilterMapper!");
227         return;
228     }
229     /* Wishlist, what Mediatypes do we want */
230     GUID mtypesin[]={MEDIATYPE_Video,MEDIASUBTYPE_MPEG2_VIDEO};
231     IEnumMoniker *myenum;
232     result = filtmap->EnumMatchingFilters(&myenum,0,TRUE,MERIT_DO_NOT_USE+1,
233                     TRUE,1,mtypesin,NULL,NULL,FALSE,TRUE,0,NULL,NULL,NULL);
234     if (result != S_OK)
235     {
236         filtmap->Release();
237         Log::getInstance()->log("VideoWin", Log::ERR , "Unable to enum Filters!");
238         return;
239     }
240     ULONG gethowmany;
241     IMoniker * moni;
242     while(myenum->Next(1,&moni,&gethowmany)==S_OK)
243     {
244         VideoFilterDesc desc;
245         ZeroMemory(&desc,sizeof(desc));
246    
247         LPOLESTR string;
248         moni->GetDisplayName(0,0,&string);
249         desc.displayname=new char[wcslen(string)+1];
250         wcstombs(desc.displayname,string,wcslen(string)+1);
251         CoTaskMemFree(string);
252         IPropertyBag *bag;
253         if (moni->BindToStorage(0,0,IID_IPropertyBag,(void**)&bag) == S_OK)
254         {
255             VARIANT vari;
256             VariantInit(&vari);
257             result = bag->Read(L"FriendlyName",&vari,NULL);
258             if (result == S_OK)
259             {
260                 desc.friendlyname=new char[wcslen(vari.bstrVal)+1];
261                 wcstombs(desc.friendlyname,vari.bstrVal,wcslen(vari.bstrVal)+1);
262             }
263             VariantClear(&vari);
264             bag->Release();
265
266         }
267         
268        
269         videofilterlist.push_back(desc);
270        
271
272         
273         moni->Release();
274        // bctx->Release();
275     }
276     int i;
277     videofilterselected=-1;
278     
279     
280   
281     myenum->Release();
282
283
284
285     filtmap->Release();
286 }
287
288 bool VideoWin::loadOptionsfromServer(VDR* vdr)
289 {
290     char *name=vdr->configLoad("DirectShow","VideoFilter");
291     
292     if (name != NULL) 
293     {
294         for (int i = 0;i <videofilterlist.size();i++)
295         {
296             if (strcmp(name,videofilterlist[i].displayname)==0)
297             {
298                 videofilterselected = i;
299                 break;
300             }
301         }
302    }
303    return true;
304
305 }
306
307 bool VideoWin::saveOptionstoServer()
308 {
309     VDR::getInstance()->configSave("DirectShow",
310         "VideoFilter",videofilterlist[videofilterselected].displayname);
311     return true;
312 }
313
314 IBaseFilter *VideoWin::getVideoFilter()
315 {
316     IBaseFilter *curfilter= NULL;
317     if (videofilterselected == -1)
318     {
319         int i;
320         for (i = 0;i <videofilterlist.size();i++)
321         {
322             
323             if (videofilterlist[i].vmr9tested == true)
324             {
325                 if (videofilterlist[i].vmr9 == true)
326                 {
327                     videofilterselected = i;
328                     break;
329                 } 
330                 else
331                 {
332                     continue;
333                 }
334             }
335             else
336             {
337                 IMoniker * moni=NULL;
338                 IBindCtx *bindctx=NULL;
339                 if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
340                 LPCOLESTR name=(LPCOLESTR)new WCHAR[strlen(videofilterlist[i].displayname)+1];
341                 mbstowcs((wchar_t*)name,videofilterlist[i].displayname,strlen(videofilterlist[i].displayname)+1);
342                 ULONG eater=0;
343                 
344
345                 if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
346                 {
347                     if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
348                     {
349                         IAMDecoderCaps* desccaps=NULL;
350                         if (curfilter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK)
351                         {
352                             DWORD caps;
353                             desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps);
354                             if (caps == DECODER_CAP_SUPPORTED)
355                             {
356                                 videofilterlist[i].vmr9tested =  true;
357                                 videofilterlist[i].vmr9 = true;
358                                 videofilterselected = i;
359                             } 
360                             else
361                             {
362                                 videofilterlist[i].vmr9tested =  true;
363                                 videofilterlist[i].vmr9 = false;
364                                 
365                                 curfilter->Release();
366                                 curfilter=NULL;
367                             }
368                         }
369                         desccaps->Release();
370                     }
371                     moni->Release();
372                 } 
373                 delete [] name;
374                 bindctx->Release();
375             }
376             if (videofilterlist[i].vmr9) break;
377             
378         }
379         if (curfilter != NULL)
380         {
381             VDR *vdr=VDR::getInstance();
382             if (vdr != NULL)
383             {
384                 vdr->configSave("DirectShow","VideoFilter",
385                     videofilterlist[videofilterselected].displayname);
386             }
387             return curfilter;
388         }
389     } 
390     else
391     {
392         IBindCtx *bindctx=NULL;
393         if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
394         IMoniker * moni=NULL;
395         LPCOLESTR name=new WCHAR[strlen(videofilterlist[videofilterselected].displayname)+1];
396         mbstowcs((wchar_t*)name,videofilterlist[videofilterselected].displayname,
397             strlen(videofilterlist[videofilterselected].displayname)+1);
398         ULONG eater;
399         if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
400         {
401             if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
402             {
403                     IAMDecoderCaps* desccaps=NULL;
404                     if (curfilter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK)
405                     {
406                         DWORD caps;
407                         desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps);
408                         if (caps == DECODER_CAP_SUPPORTED)
409                         {
410                             videofilterlist[videofilterselected].vmr9tested =  true;
411                             videofilterlist[videofilterselected].vmr9 = true;
412                         } 
413                         else
414                         {
415                             videofilterlist[videofilterselected].vmr9tested =  true;
416                             videofilterlist[videofilterselected].vmr9 = false;
417                             Log::getInstance()->log("VideoWin", Log::WARN ,"Filter does not support VMR9, but is selected, manual selection!");
418                         }
419                     }
420                     moni->Release();
421                     delete [] name;
422                     bindctx->Release();
423                     return curfilter;
424              } 
425             moni->Release();
426         }
427         bindctx->Release();
428         delete [] name;
429         return NULL;         
430     }
431     return NULL;
432     
433 }
434
435
436 #ifdef DS_DEBUG // This stuff would not included in vomp due to lincemse restrcitions
437 #include "dshelper.h"
438 #endif
439
440 #define DO_VIDEO
441
442 int VideoWin::play()
443 {
444   if (!initted) return 0;
445   return 1;
446 }
447
448 bool VideoWin::addOptionPagesToWTB(WTabBar *wtb)
449 {
450     Boxx *box=new WWinVideoFilter();
451     wtb->addTab(tr("Video Filter"), box);
452     return true;
453 }
454
455 const VideoFilterDescList *VideoWin::getVideoFilterList(int &selected)
456 {
457     selected=videofilterselected;
458     return &videofilterlist;
459 }
460
461 bool VideoWin::selectVideoFilter(int filter)
462 {
463     IBindCtx *bindctx=NULL;
464     if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
465     IMoniker * moni=NULL;
466     LPCOLESTR name=new WCHAR[strlen(videofilterlist[filter].displayname)+1];
467     mbstowcs((wchar_t*)name,videofilterlist[filter].displayname,
468     strlen(videofilterlist[filter].displayname)+1);
469     ULONG eater;
470     bool success=false;
471     if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
472     {
473         IBaseFilter* curfilter=NULL;
474         if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
475         {
476             IAMDecoderCaps* desccaps=NULL;
477             if (curfilter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK)
478             {
479                 DWORD caps;
480                 HRESULT hres=desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps);
481                 if (caps == DECODER_CAP_SUPPORTED)
482                 {
483                     videofilterlist[filter].vmr9tested =  true;
484                     videofilterlist[filter].vmr9 = true;
485                     success=true;
486                 } 
487                 else
488                 {
489                     videofilterlist[filter].vmr9tested =  true;
490                     videofilterlist[filter].vmr9 = false;
491                     success=false;
492                  }
493                 desccaps->Release();
494             } else {
495                 videofilterlist[filter].vmr9tested =  true;
496                 videofilterlist[filter].vmr9 = false;
497                 success=false;
498             }
499
500              curfilter->Release();
501              
502         } 
503         moni->Release();
504     }
505     bindctx->Release();
506     delete [] name;
507     if (success) 
508     {
509         videofilterselected=filter;
510         return true;
511     } 
512     else
513     {
514         return false;
515     }
516 }
517
518
519 int VideoWin::dsInitVideoFilter()
520 {
521     #ifdef DO_VIDEO
522     HRESULT hres;
523     if (videoon) {
524     //We alloc the vmr9 as next step
525         if (hres=CoCreateInstance(CLSID_VideoMixingRenderer9,0,
526             CLSCTX_INPROC_SERVER,IID_IBaseFilter,(void**) &dsvmrrenderer)!=S_OK) 
527         {
528             Log::getInstance()->log("VideoWin", Log::WARN ,"Failed creating VMR9 renderer!");
529                 ReleaseMutex(filtermutex);
530             CleanupDS();
531         }
532         /*VMR 9 stuff**/
533         if (hres=dsgraphbuilder->AddFilter(dsvmrrenderer,L"VMR9")!=S_OK)
534         {
535             ReleaseMutex(filtermutex);
536             CleanupDS();
537             Log::getInstance()->log("VideoWin", Log::WARN ,"Failed adding VMR9 renderer!");
538             return 0;
539         }
540         IVMRFilterConfig9* vmrfilconfig;
541         if (dsvmrrenderer->QueryInterface(IID_IVMRFilterConfig9,(void**)&vmrfilconfig)!=S_OK)
542         {
543             ReleaseMutex(filtermutex);
544             CleanupDS();
545             Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Filterconfig interface!");
546             return 0;
547         }
548         vmrfilconfig->SetRenderingMode(VMR9Mode_Renderless);
549         vmrfilconfig->Release();
550
551         if (dsvmrrenderer->QueryInterface(IID_IVMRSurfaceAllocatorNotify9,
552             (void**)& dsvmrsurfnotify) != S_OK)
553         {
554             ReleaseMutex(filtermutex);
555                 CleanupDS();
556             Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Surface Allocator interface!");
557             return 0;
558         }
559         allocatorvmr=new DsAllocator();
560         dsvmrsurfnotify->AdviseSurfaceAllocator(NULL,allocatorvmr);
561         allocatorvmr->AdviseNotify(dsvmrsurfnotify);
562        /*VMR 9 stuff end */
563         IFilterGraph2*fg2=NULL;
564         if (dsgraphbuilder->QueryInterface(IID_IFilterGraph2,(void**)&fg2)!= S_OK)
565         {
566             Log::getInstance()->log("VideoWin", Log::WARN , "Failed querying for FilterGraph2 Interface!");
567             ReleaseMutex(filtermutex);
568                 CleanupDS();
569             return 0;
570         }
571 /*#ifndef NEW_DS_MECHANISMENS
572         
573         if (hres=fg2->RenderEx((IPin*)sourcefilter->GetVideoPin()/*video*,
574             AM_RENDEREX_RENDERTOEXISTINGRENDERERS,NULL) != S_OK) 
575         {
576             Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering Video!");
577                 fg2->Release();
578                 ReleaseMutex(filtermutex);
579                 CleanupDS();
580             return 0;
581         }
582         
583 #else*/
584         IBaseFilter*videofilter=getVideoFilter();
585         if (hres=dsgraphbuilder->AddFilter(videofilter,NULL) != S_OK) 
586         {
587             Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Video Filter!");
588             ReleaseMutex(filtermutex);
589             CleanupDS();
590             return 0;
591         }
592         IEnumPins *pinenum=NULL;
593         bool error=false;
594         if (videofilter->EnumPins(&pinenum) == S_OK)
595         {
596             IPin *current=NULL;
597             ULONG fetch=0;
598             bool firststep=false;
599
600             while (pinenum->Next(1,&current,&fetch)==S_OK)
601             {
602                 PIN_DIRECTION dir;
603                 if (current->QueryDirection(&dir)==S_OK)
604                 {
605                     if (dir == PINDIR_INPUT)
606                     {
607                         if (sourcefilter->GetVideoPin()->Connect(current,NULL)==S_OK)
608                         {
609                             current->Release();
610                             firststep=true;
611                             break;
612                         }
613                     }
614                 }
615                 current->Release();
616             }
617             if (firststep==false)
618             {
619                 Log::getInstance()->log("VideoWin", Log::WARN , "Video Filter has no suitable input!");
620                 videofilter->Release();
621                 ReleaseMutex(filtermutex);
622                 CleanupDS();
623                 return 0;
624             }
625             bool secondstep=false;
626             pinenum->Reset();
627             while (pinenum->Next(1,&current,&fetch)==S_OK)
628             {
629                 PIN_DIRECTION dir;
630                 if (current->QueryDirection(&dir)==S_OK)
631                 {
632                     if (dir == PINDIR_OUTPUT)
633                     {
634                         
635                         if (fg2->RenderEx((IPin*)current/*video*/,
636                                 AM_RENDEREX_RENDERTOEXISTINGRENDERERS,NULL) ==S_OK)
637                         {
638                             current->Release();
639                             secondstep=true;
640                             break;
641                         }
642                     }
643                 }
644                 current->Release();
645             }
646             if (secondstep==false)
647             {
648                 Log::getInstance()->log("VideoWin", Log::WARN , "Video Filter has no suitable output!");
649                 videofilter->Release();
650                 ReleaseMutex(filtermutex);
651                 CleanupDS();
652                 return 0;
653             }
654             
655             videofilter->Release();
656             pinenum->Release();
657
658         }
659
660
661
662         fg2->Release();
663         return 1;
664     }
665 #endif 
666
667 }
668
669 int VideoWin::setAudioStreamType(UCHAR type)
670 {
671   aud_type=type;
672   if (!initted) return 0;
673   return 1;
674 }
675
676 int VideoWin::dsplay()
677 {
678     if (!initted) return 0;
679     CleanupDS();
680     
681     //Build filter graph
682     HRESULT hres;
683     //So this is the real code, this prevents the feeder from calling noexisting objects!
684     WaitForSingleObject(filtermutex,INFINITE);
685     if (hres=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,
686         IID_IGraphBuilder,(void**)&dsgraphbuilder) != S_OK) 
687     {
688         ReleaseMutex(filtermutex);
689         return 0;
690     }
691    #ifdef DS_DEBUG
692    AddToRot(dsgraphbuilder,&graphidentifier);
693    #endif
694    
695    firstsynched=false;
696    if (aud_type==Audio::MP3) {
697        lastaudiomode=MPTYPE_MPEG_AUDIO_LAYER3;
698    } else {
699        lastaudiomode=MPTYPE_MPEG_AUDIO;
700    }
701    //lastaudiomode=MPTYPE_AC3;
702    sourcefilter=new DsSourceFilter(); //Creating our Source filter for pushing Data
703    // to DirectShow
704    if (hres=dsgraphbuilder->AddFilter(sourcefilter,L"Vomp Win Source Filter") != S_OK) 
705    {
706        Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Vomp Source Filter!");
707        ReleaseMutex(filtermutex);
708        CleanupDS();
709        return 0;
710    }
711    sourcefilter->GetAudioPin()->SetPinMode(lastaudiomode);
712    /*if (hres=dsgraphbuilder->Render((IPin*)sourcefilter->GetAudioPin()/*audio*)!=S_OK) 
713    {
714        Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering audio!");
715            ReleaseMutex(filtermutex);
716        CleanupDS();
717        return 0;
718    }*/
719    if (((AudioWin*)Audio::getInstance())->dsInitAudioFilter(dsgraphbuilder)==0)
720    {
721        Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering audio!");
722            ReleaseMutex(filtermutex);
723        CleanupDS();
724        return 0;
725    }
726
727
728     if (dsInitVideoFilter()==0)
729     { 
730         return 0;
731     }
732
733     if (hres=CoCreateInstance(CLSID_SystemClock,NULL,CLSCTX_INPROC_SERVER,
734         IID_IReferenceClock,(void**)&dsrefclock)!=S_OK) 
735     {
736         return 0;
737     }
738     dsgraphbuilder->QueryInterface(IID_IMediaFilter,(void **) &dsmediafilter);
739     HRESULT hresdeb = dsmediafilter->SetSyncSource(dsrefclock);
740
741     dsgraphbuilder->QueryInterface(IID_IMediaControl,(void **) &dsmediacontrol);
742     dsgraphbuilder->QueryInterface(IID_IBasicAudio,(void **) &dsbasicaudio);    
743     if (dsbasicaudio) 
744        dsbasicaudio->put_Volume(audiovolume);
745     dsinited=true;
746    //MILLISLEEP(100);
747
748     hresdeb=dsmediacontrol->Run();
749     iframemode=false;//exit iframe mode
750     ReleaseMutex(filtermutex);
751     return 1;
752 }
753
754 int VideoWin::EnterIframePlayback()
755 {
756         if (!initted) return 0;
757         CleanupDS();
758         //So this is the real code, this prevents the feeder from calling noexisting objects!
759    WaitForSingleObject(filtermutex,INFINITE);
760         iframemode=true;//enter iframe mode
761         //Build filter graph
762         HRESULT hres;
763         if (hres=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,
764                  IID_IGraphBuilder,(void**)&dsgraphbuilder)!=S_OK) {
765                          ReleaseMutex(filtermutex);
766                          return 0;
767         }
768 #ifdef DS_DEBUG
769         AddToRot(dsgraphbuilder,&graphidentifier);
770 #endif
771    
772    //firstsynched=false;
773    sourcefilter=new DsSourceFilter(); //Creating our Source filter for pushing Data
774    // to DirectShow
775    if (hres=dsgraphbuilder->AddFilter(sourcefilter,L"Vomp Win Source Filter")!=S_OK) {
776    Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Vomp Source Filter!");
777      ReleaseMutex(filtermutex);  
778      CleanupDS();
779      return 0;
780    }
781 #ifdef DO_VIDEO
782     if (videoon) {
783         dsInitVideoFilter();
784    }
785 #endif
786 /*   if (hres=CoCreateInstance(CLSID_SystemClock,NULL,CLSCTX_INPROC_SERVER,
787     IID_IReferenceClock,(void**)&dsrefclock)!=S_OK) {
788       return 0;
789    }*/
790
791    dsgraphbuilder->QueryInterface(IID_IMediaFilter,(void **) &dsmediafilter);
792    dsmediafilter->SetSyncSource(/*dsrefclock*/NULL); //Run as fast as you can!
793
794    dsgraphbuilder->QueryInterface(IID_IMediaControl,(void **) &dsmediacontrol);
795    dsgraphbuilder->QueryInterface(IID_IBasicAudio,(void **) &dsbasicaudio);     
796   dsinited=true;
797   
798
799    dsmediacontrol->Run();
800    ReleaseMutex(filtermutex);
801   return 1;
802
803 }
804
805 int VideoWin::dsstop()
806 {
807   if (!initted) return 0;
808
809   CleanupDS();
810
811
812   return 1;
813 }
814
815 int VideoWin::stop()
816 {
817   if (!initted) return 0;
818
819
820   return 1;
821 }
822
823 int VideoWin::reset()
824 {
825   if (!initted) return 0;
826   
827
828   return 1;
829 }
830
831 int VideoWin::dsreset()
832 {
833   if (!initted) return 0;
834   videoposx=0;
835   videoposy=0;
836   iframemode=false;//exit iframe mode
837   CleanupDS();
838
839   return 1;
840 }
841
842 int VideoWin::dspause()
843 {
844   if (!initted) return 0;
845   WaitForSingleObject(filtermutex,INFINITE);
846   if (dsmediacontrol) dsmediacontrol->Pause();
847   ReleaseMutex(filtermutex);
848   return 1;
849 }
850
851 int VideoWin::pause()
852 {
853   if (!initted) return 0;
854   
855   return 1;
856 }
857
858 int VideoWin::unPause() // FIXME get rid - same as play!!
859 {//No on windows this is not the same, I don't get rid of!
860   if (!initted) return 0;
861   return 1;
862 }
863
864 int VideoWin::dsunPause() // FIXME get rid - same as play!!
865 {//No on windows this is not the same, I don't get rid of!
866   if (!initted) return 0;
867   WaitForSingleObject(filtermutex,INFINITE);
868   if (dsmediacontrol) dsmediacontrol->Run();
869   ReleaseMutex(filtermutex);
870
871   return 1;
872 }
873
874 int VideoWin::fastForward()
875 {
876   if (!initted) return 0;
877
878   return 1;
879 }
880
881 int VideoWin::unFastForward()
882 {
883   if (!initted) return 0;
884   
885   return 1;
886 }
887
888 int VideoWin::attachFrameBuffer()
889 {
890   if (!initted) return 0;
891   return 1;
892 }
893
894 int VideoWin::blank(void)
895 {
896   ((OsdWin*)Osd::getInstance())->Blank();
897   return 1;
898 }
899
900 ULLONG VideoWin::getCurrentTimestamp()
901 {
902         REFERENCE_TIME startoffset;
903         REFERENCE_TIME ncr_time;
904   if (iframemode) return 0; //Not in iframe mode!
905   if (!dsrefclock || !sourcefilter) return 0;
906         FILTER_STATE state;
907         sourcefilter->GetState(10,&state);
908
909         if (state==State_Running) dsrefclock->GetTime(&cr_time);
910         ncr_time=cr_time;
911   startoffset=sourcefilter->getStartOffset();
912         ncr_time-=startoffset;
913         ncr_time-=lastreftimeRT;
914  /* ULLONG result=frameNumberToTimecode(
915     VDR::getInstance()->frameNumberFromPosition(lastreftimeBYTE));*/
916         ULLONG result=lastreftimePTS;
917         result+=(ULLONG)(ncr_time/10000LL*90LL);
918   return result;
919
920 }
921
922 ULONG VideoWin::timecodeToFrameNumber(ULLONG timecode)
923 {
924   if (format == PAL) return (ULONG)(((double)timecode / (double)90000) * (double)25);
925   else               return (ULONG)(((double)timecode / (double)90000) * (double)30);
926 }
927
928 ULLONG VideoWin::frameNumberToTimecode(ULONG framenumber)
929 {
930   if (format == PAL) return (ULLONG)(((double)framenumber * (double)90000) / (double)25);
931   else               return (ULLONG)(((double)framenumber * (double)90000) / (double)30);
932 }
933
934 void VideoWin::CleanupDS()
935 {
936   WaitForSingleObject(filtermutex,INFINITE);
937   dsinited=false;
938   if (dsmediacontrol)dsmediacontrol->Stop();
939   if (cur_audio_media_sample) {
940     cur_audio_media_sample->Release();
941     cur_audio_media_sample=NULL;
942   }
943   if (cur_video_media_sample) {
944     cur_video_media_sample->Release();
945     cur_video_media_sample=NULL;
946   }
947   if (dsbasicaudio) {
948           dsbasicaudio->Release();
949           dsbasicaudio=NULL;
950   }
951   if (dsvmrsurfnotify) {
952     dsvmrsurfnotify->Release();
953     dsvmrsurfnotify=NULL;
954   }
955   if (dsvmrrenderer) {
956     dsvmrrenderer->Release();
957     dsvmrrenderer=NULL;
958   }
959
960   if (allocatorvmr) {
961     allocatorvmr->Release();
962     allocatorvmr=NULL;
963   }
964
965   if (dsrefclock) {
966     dsrefclock->Release();
967     dsrefclock=NULL;
968   }
969   if (dsmediafilter) {
970     dsmediafilter->Release();
971     dsmediafilter=NULL;
972   }
973
974
975
976   if (dsmediacontrol) {
977     dsmediacontrol->Stop();
978     dsmediacontrol->Release();
979     dsmediacontrol=NULL;
980   }
981   if (dsgraphbuilder){
982 #ifdef DS_DEBUG
983     RemoveFromRot(graphidentifier);
984 #endif
985         dsgraphbuilder->Release();
986     dsgraphbuilder=NULL;
987         
988     sourcefilter=NULL; //The Graph Builder destroys our SourceFilter
989   }
990   ReleaseMutex(filtermutex);
991
992 }
993
994 void VideoWin::PrepareMediaSample(const MediaPacketList& mplist,
995      UINT samplepos)
996 {
997   mediapacket = mplist.front();
998 }
999
1000 UINT VideoWin::DeliverMediaSample(const UCHAR* buffer, UINT *samplepos)
1001 {
1002   DeliverMediaPacket(mediapacket, buffer, samplepos);
1003   if (*samplepos == mediapacket.length) {
1004     *samplepos = 0;
1005     return 1;
1006   }
1007   else return 0;
1008 }
1009
1010 UINT VideoWin::DeliverMediaPacket(MediaPacket packet,
1011      const UCHAR* buffer,
1012      UINT *samplepos)
1013 {
1014     
1015   /*First Check, if we have an audio sample*/
1016         if (!isdsinited()) return 0;
1017 #ifdef DO_VIDEO
1018         if (!videoon) {
1019           *samplepos+=packet.length;
1020        MILLISLEEP(0); //yet not implemented//bad idea
1021        return packet.length;
1022         }
1023   /*First Check, if we have an audio sample*/
1024   if (iframemode) {
1025                 samplepos=0;
1026                 MILLISLEEP(10);
1027                 return 0; //Not in iframe mode!
1028   }
1029   IMediaSample* ms=NULL;
1030   REFERENCE_TIME reftime1=0;
1031   REFERENCE_TIME reftime2=0;
1032
1033   UINT headerstrip=0;
1034   if (packet.disconti) {
1035     firstsynched=false;
1036     DeliverVideoMediaSample();
1037
1038   }
1039   /*Inspect PES-Header */
1040
1041   if (*samplepos==0) {//stripheader
1042     headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/;
1043     *samplepos+=headerstrip;
1044     if ( packet.synched ) {
1045       DeliverVideoMediaSample();//write out old data
1046    /*   if (packet.presentation_time<0) { //Preroll?
1047         *samplepos=packet.length;//if we have not processed at least one
1048         return packet.length;//synched packet ignore it!
1049       }*/
1050
1051       reftime1=packet.presentation_time;
1052       reftime2=reftime1+1;
1053       firstsynched=true;
1054     } else {
1055       if (!firstsynched) {//
1056         *samplepos=packet.length;//if we have not processed at least one
1057         return packet.length;//synched packet ignore it!
1058       }
1059     }
1060   }
1061   BYTE *ms_buf;
1062   UINT ms_length;
1063   UINT ms_pos;
1064   UINT haveToCopy;
1065   
1066   if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
1067     samplepos=0;
1068     MILLISLEEP(10);
1069     return 0;
1070   }
1071   ms_pos=ms->GetActualDataLength();
1072   ms_length=ms->GetSize();
1073   haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);
1074   if ((ms_length-ms_pos)<1) {
1075     DeliverVideoMediaSample(); //we are full!
1076     if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
1077       samplepos=0;
1078       MILLISLEEP(10);
1079       return 0;
1080     }
1081     ms_pos=ms->GetActualDataLength();
1082     ms_length=ms->GetSize();
1083     haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);
1084   }
1085   ms->GetPointer(&ms_buf);
1086
1087
1088   if (ms_pos==0) {//will only be changed on first packet
1089     if (packet.disconti) {
1090       ms->SetDiscontinuity(TRUE);
1091     } else {
1092       ms->SetDiscontinuity(FALSE);
1093     }
1094     if (packet.synched) {
1095       ms->SetSyncPoint(TRUE);
1096       ms->SetTime(&reftime1,&reftime2);
1097       //ms->SetTime(NULL,NULL);
1098       ms->SetMediaTime(NULL, NULL);
1099     if (reftime1<0) ms->SetPreroll(TRUE);
1100     else ms->SetPreroll(FALSE);
1101     /*Timecode handling*/
1102     lastreftimeRT=reftime1;
1103         lastreftimePTS=packet.pts;
1104
1105     }else {
1106       ms->SetSyncPoint(FALSE);
1107       ms->SetTime(NULL,NULL);
1108       ms->SetMediaTime(NULL, NULL);
1109       ms->SetPreroll(FALSE);
1110
1111     //  ms->SetSyncPoint(TRUE);
1112     }
1113   }
1114
1115
1116   memcpy(ms_buf+ms_pos,buffer+packet.pos_buffer+*samplepos,haveToCopy);
1117     ms->SetActualDataLength(haveToCopy+ms_pos);
1118
1119   *samplepos+=haveToCopy;
1120
1121   return haveToCopy+headerstrip;
1122
1123 #else
1124
1125        *samplepos+=packet.length;
1126       MILLISLEEP(0); //yet not implemented//bad idea
1127        return packet.length;
1128 #endif
1129 }
1130
1131 int VideoWin::getCurrentAudioMediaSample(IMediaSample** ms)
1132 {
1133   //WaitForSingleObject(filtermutex,INFINITE);
1134   if (!sourcefilter){
1135   //  ReleaseMutex(filtermutex);
1136     return 0;
1137   }
1138   if (cur_audio_media_sample) {
1139     *ms=cur_audio_media_sample;//already open
1140     return 1;
1141   }
1142   if (!sourcefilter->getCurrentAudioMediaSample(ms)) {
1143   //  ReleaseMutex(filtermutex);
1144   }
1145   if (*ms) (*ms)->SetActualDataLength(0);
1146   cur_audio_media_sample=*ms;
1147   //Don't release the mutex before deliver
1148   return 1;
1149 }
1150
1151 int VideoWin::getCurrentVideoMediaSample(IMediaSample** ms)
1152 {
1153   //WaitForSingleObject(filtermutex,INFINITE);
1154   if (!sourcefilter){
1155   //  ReleaseMutex(filtermutex);
1156     return 0;
1157   }
1158   if (cur_video_media_sample) {
1159     *ms=cur_video_media_sample;//already open
1160     return 1;
1161   }
1162   if (!sourcefilter->getCurrentVideoMediaSample(ms)) {
1163   //  ReleaseMutex(filtermutex);
1164   }
1165   if (*ms) (*ms)->SetActualDataLength(0);
1166
1167   cur_video_media_sample=*ms;
1168   //Don't release the mutex before deliver
1169   return 1;
1170 }
1171
1172 int VideoWin::DeliverAudioMediaSample(){
1173   if (cur_audio_media_sample) {
1174     sourcefilter->DeliverAudioMediaSample(cur_audio_media_sample);
1175     cur_audio_media_sample=NULL;
1176   }
1177   //ReleaseMutex(filtermutex);
1178   return 1;
1179 }
1180
1181 int VideoWin::DeliverVideoMediaSample(){
1182   if (cur_video_media_sample) {
1183     sourcefilter->DeliverVideoMediaSample(cur_video_media_sample);
1184     cur_video_media_sample=NULL;
1185   }
1186   //ReleaseMutex(filtermutex);
1187   return 1;
1188 }
1189
1190 long long VideoWin::SetStartOffset(long long curreftime, bool *rsync)
1191 {
1192   *rsync=false;
1193   if (offsetnotset) {
1194     startoffset=curreftime;//offset is set for audio
1195     offsetnotset=false;
1196     offsetvideonotset=false;
1197
1198
1199   } else {
1200     if (offsetvideonotset) {
1201       offsetvideonotset=false;
1202       *rsync=true;
1203     } else {
1204       if ( (curreftime-lastrefvideotime)>10000000LL
1205         || (curreftime-lastrefvideotime)<-10000000LL) {//if pts jumps to big resync
1206         startoffset+=curreftime-lastrefvideotime;
1207         lastrefaudiotime+=curreftime-lastrefvideotime;
1208         //*rsync=true;
1209         offsetaudionotset=true;
1210
1211       }
1212     }
1213
1214   }
1215
1216   lastrefvideotime=curreftime;
1217   
1218   return startoffset;
1219
1220 }
1221
1222 long long VideoWin::SetStartAudioOffset(long long curreftime, bool *rsync)
1223 {
1224   *rsync=false;
1225   if (offsetnotset) {
1226     startoffset=curreftime;
1227     offsetnotset=false;
1228     offsetaudionotset=false;
1229   }else {
1230     if (offsetaudionotset) {
1231       offsetaudionotset=false;
1232       *rsync=true;
1233     } else {
1234       if ( (curreftime-lastrefaudiotime)>10000000LL
1235         || (curreftime-lastrefaudiotime)<-10000000LL) {//if pts jumps to big resync
1236         startoffset+=curreftime-lastrefaudiotime;
1237         lastrefvideotime+=curreftime-lastrefaudiotime;
1238         //*rsync=true;
1239         offsetvideonotset=true;
1240
1241       }
1242     }
1243
1244   }
1245   lastrefaudiotime=curreftime;
1246   return startoffset;
1247
1248 }
1249 void VideoWin::ResetTimeOffsets() {
1250   offsetnotset=true; //called from demuxer
1251   offsetvideonotset=true;
1252   offsetaudionotset=true;
1253   startoffset=0;
1254   lastrefaudiotime=0;
1255   lastrefvideotime=0;
1256   lastreftimeRT=0;
1257   lastreftimePTS=0;
1258
1259
1260 }
1261
1262 void VideoWin::SetAudioVolume(long volume)
1263 {
1264     audiovolume=volume;
1265         if (dsbasicaudio) dsbasicaudio->put_Volume(volume);
1266 }
1267
1268 void VideoWin::displayIFrame(const UCHAR* buffer, UINT length)
1269 {
1270         if (!iframemode) EnterIframePlayback();
1271
1272         if (!isdsinited()) return ;
1273 #ifdef DO_VIDEO
1274   IMediaSample* ms=NULL;
1275   REFERENCE_TIME reftime1=0;
1276   REFERENCE_TIME reftime2=0;
1277   if (!videoon) return;
1278
1279   if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
1280     MILLISLEEP(10);
1281     return ;
1282   }
1283   BYTE *ms_buf;
1284   DWORD ms_length;
1285   ms->GetPointer(&ms_buf);
1286   ms_length=ms->GetSize();
1287   
1288   /*First Check, if we have an video sample*/
1289   DWORD read_pos = 0, write_pos = 0;
1290   DWORD pattern, packet_length;
1291   DWORD headerstrip=0;
1292   bool first=true;
1293   if (length < 4) return ;
1294   //Now we strip the pes header
1295   pattern = (buffer[0] << 16) | (buffer[1] << 8) | (buffer[2]);
1296   while (read_pos + 7 <= length)
1297   {
1298     pattern = ((pattern << 8) & 0xFFFFFFFF) | buffer[read_pos+3];
1299     if (pattern < 0x000001E0 || pattern > 0x000001EF)
1300       read_pos++;
1301     else
1302     {
1303           headerstrip=buffer[read_pos+8]+9/*is this right*/;
1304       packet_length = ((buffer[read_pos+4] << 8) | (buffer[read_pos+5])) + 6;
1305       if (read_pos + packet_length > length)
1306         read_pos = length;
1307       else
1308       {
1309                   if ((write_pos+packet_length-headerstrip)>ms_length) {
1310                           if (first) {
1311                   ms->SetSyncPoint(TRUE);
1312                   ms->SetDiscontinuity(TRUE);
1313                   first=false;
1314               } else ms->SetSyncPoint(FALSE);
1315                           ms->SetTime(NULL,NULL);
1316                           ms->SetMediaTime(NULL, NULL);
1317                           ms->SetActualDataLength(write_pos);
1318                           DeliverVideoMediaSample();
1319
1320                           if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
1321                                 MILLISLEEP(10);
1322                                 return ;
1323                           }
1324                           write_pos=0;
1325                           ms_length=ms->GetSize();
1326                           ms->GetPointer(&ms_buf);
1327                   }
1328                   if (packet_length>headerstrip) {
1329                         memcpy(ms_buf+write_pos, buffer+read_pos+headerstrip, packet_length-headerstrip);
1330                         write_pos += packet_length-headerstrip;
1331                   }
1332                   read_pos += packet_length;
1333                   
1334                   pattern = (buffer[read_pos] << 16) | (buffer[read_pos+1] << 8)
1335                                         | (buffer[read_pos+2]);
1336       }
1337     }
1338   }
1339
1340   if (first) {ms->SetSyncPoint(TRUE);first=false;} 
1341   else ms->SetSyncPoint(FALSE);
1342   ms->SetTime(NULL,NULL);
1343   ms->SetMediaTime(NULL, NULL);
1344   ms->SetActualDataLength(write_pos);
1345   DeliverVideoMediaSample();
1346
1347 #else
1348
1349     //   *samplepos+=packet.length;
1350       MILLISLEEP(0); //yet not implemented//bad idea
1351        return ;
1352 #endif
1353 }
1354
1355 bool VideoWin::supportsAc3(){
1356     if (sourcefilter != NULL) {
1357         return sourcefilter->supportsAc3();
1358     } else {
1359         return false;
1360     }
1361 }
1362
1363 bool VideoWin::changeAType(int type,IMediaSample* ms){
1364     if (sourcefilter!= NULL) {
1365         lastaudiomode=type;
1366         return sourcefilter->changeAType(type,ms);
1367     }
1368     else 
1369     {
1370         return false;
1371     }
1372 }
1373
1374 #ifdef DEV
1375 int VideoWin::test()
1376 {
1377   return 0;
1378 }
1379
1380 int VideoWin::test2()
1381 {
1382   return 0;
1383 }
1384 #endif
1385
1386
1387
1388