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