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