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