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