]> git.vomp.tv Git - vompclient.git/blob - videowin.cc
MVP/Windows convergence
[vompclient.git] / videowin.cc
1 /*\r
2     Copyright 2004-2005 Chris Tallon\r
3 \r
4     This file is part of VOMP.\r
5 \r
6     VOMP is free software; you can redistribute it and/or modify\r
7     it under the terms of the GNU General Public License as published by\r
8     the Free Software Foundation; either version 2 of the License, or\r
9     (at your option) any later version.\r
10 \r
11     VOMP is distributed in the hope that it will be useful,\r
12     but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14     GNU General Public License for more details.\r
15 \r
16     You should have received a copy of the GNU General Public License\r
17     along with VOMP; if not, write to the Free Software\r
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
19 */\r
20 \r
21 #include "videowin.h"\r
22 #include "log.h"\r
23 #include "dssourcefilter.h"\r
24 #include "dsallocator.h"\r
25 #include "vdr.h"\r
26 #include "osdwin.h"\r
27 \r
28 void AdjustWindow();\r
29 \r
30 \r
31 \r
32 VideoWin::VideoWin()\r
33 {\r
34   dsgraphbuilder=NULL;\r
35   dsmediacontrol=NULL;\r
36   dsvmrrenderer=NULL;\r
37   dsrefclock=NULL;\r
38   dsmediafilter=NULL;\r
39   dsbasicaudio=NULL;\r
40   sourcefilter=NULL;\r
41   allocatorvmr=NULL;\r
42   cr_time=0;\r
43   dsvmrsurfnotify=NULL;\r
44   filtermutex=CreateMutex(NULL,FALSE,NULL);\r
45   offsetnotset=true;\r
46   offsetvideonotset=true;\r
47   offsetaudionotset=true;\r
48   startoffset=0;\r
49   lastrefaudiotime=0;\r
50   lastrefvideotime=0;\r
51   lastreftimeRT=0;\r
52   lastreftimePTS=0;\r
53   firstsynched=false;\r
54   cur_audio_media_sample=NULL;\r
55   cur_video_media_sample=NULL;\r
56   videoon=true;\r
57   audioon=true;\r
58   pseudotvsize=0;\r
59   videoposx=0;\r
60   videoposy=0;\r
61 \r
62 \r
63 \r
64 }\r
65 \r
66 VideoWin::~VideoWin()\r
67 {\r
68   CleanupDS();\r
69   CloseHandle(filtermutex);\r
70 \r
71 \r
72 \r
73   instance = NULL;\r
74 }\r
75 \r
76 int VideoWin::init(UCHAR tformat)\r
77 {\r
78   if (initted) return 0;\r
79 \r
80   initted = 1;\r
81   tvsize=Video::ASPECT16X9; //Internally Vomp should think we are a 16:9 TV\r
82   videoposx=0;\r
83   videoposy=0;\r
84 \r
85   if (!setFormat(tformat)){ shutdown(); return 0; }\r
86   return 1;\r
87 }\r
88 \r
89 int VideoWin::setTVsize(UCHAR ttvsize)\r
90 {\r
91   pseudotvsize=ttvsize;\r
92   return 1;\r
93 }\r
94 \r
95 int VideoWin::setDefaultAspect()\r
96 {\r
97   return setAspectRatio(Video::ASPECT4X3);\r
98 }\r
99 \r
100 int VideoWin::shutdown()\r
101 {\r
102   if (!initted) return 0;\r
103   initted = 0;\r
104   return 1;\r
105 }\r
106 \r
107 int VideoWin::setFormat(UCHAR tformat)\r
108 {\r
109   if (!initted) return 0;\r
110   if ((tformat != PAL) && (tformat != NTSC)) return 0;\r
111   format = tformat;\r
112   if (format == NTSC)\r
113   {\r
114     screenWidth = 720;\r
115     screenHeight = 480;\r
116   }\r
117   if (format == PAL)\r
118   {\r
119     screenWidth = 720;\r
120     screenHeight = 576;\r
121   }\r
122 \r
123   return 1;\r
124 }\r
125 \r
126 int VideoWin::setConnection(UCHAR tconnection)\r
127 {\r
128   if (!initted) return 0;\r
129   if ((tconnection != COMPOSITERGB) && (tconnection != SVIDEO)) return 0;\r
130   connection = tconnection;\r
131 \r
132   return 1;\r
133 }\r
134 \r
135 int VideoWin::setAspectRatio(UCHAR taspectRatio)\r
136 {\r
137   if (!initted) return 0;\r
138   if ((taspectRatio != ASPECT4X3) && (taspectRatio != ASPECT16X9)) return 0;\r
139   aspectRatio = taspectRatio;\r
140   AdjustWindow();\r
141   return 1;\r
142 }\r
143 \r
144 int VideoWin::setMode(UCHAR tmode)\r
145 {\r
146   if (!initted) return 0;\r
147 \r
148   //if ((tmode == LETTERBOX) && (tvsize == ASPECT16X9)) return 0; // invalid mode\r
149 \r
150   if ((tmode != NORMAL) && (tmode != LETTERBOX) && (tmode != UNKNOWN2) && (tmode != QUARTER) && (tmode != EIGHTH)\r
151       && (tmode != ZOOM) && (tmode != UNKNOWN6)) return 0;\r
152   mode = tmode;\r
153   videoposx=0;\r
154   videoposy=0;\r
155   AdjustWindow();\r
156 \r
157   return 1;\r
158 }\r
159 \r
160 int VideoWin::signalOff()\r
161 {\r
162   return 1;\r
163 }\r
164 \r
165 int VideoWin::signalOn()\r
166 {\r
167   return 1;\r
168 }\r
169 \r
170 int VideoWin::setSource()\r
171 {\r
172   if (!initted) return 0;\r
173 \r
174   return 1;\r
175 }\r
176 \r
177 int VideoWin::setPosition(int x, int y)\r
178 {\r
179   if (!initted) return 0;\r
180   if (mode==QUARTER || mode==EIGHTH) {\r
181   videoposx=x;\r
182   videoposy=y;\r
183   }\r
184   return 1;\r
185 }\r
186 \r
187 int VideoWin::sync()\r
188 {\r
189   if (!initted) return 0;\r
190 \r
191   return 1;\r
192 }\r
193 \r
194 #ifdef DS_DEBUG // This stuff would not included in vomp due to lincemse restrcitions\r
195 #include "dshelper.h"\r
196 #endif\r
197 \r
198 #define DO_VIDEO\r
199 \r
200 int VideoWin::play()\r
201 {\r
202   if (!initted) return 0;\r
203 \r
204   //Build filter graph\r
205   HRESULT hres;\r
206 \r
207   if (hres=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,\r
208     IID_IGraphBuilder,(void**)&dsgraphbuilder)!=S_OK) {\r
209       return 0;\r
210    }\r
211    #ifdef DS_DEBUG\r
212    AddToRot(dsgraphbuilder,&graphidentifier);\r
213    #endif\r
214    //This is just a try to see if building the graph works\r
215 //   dsgraphbuilder->RenderFile(L"D:\\Projekte\\VTP Client\\test.mpa" ,NULL);\r
216    //So this is the real code, this prevents the feeder from calling noexisting objects!\r
217    WaitForSingleObject(filtermutex,INFINITE);\r
218    firstsynched=false;\r
219    sourcefilter=new DsSourceFilter(); //Creating our Source filter for pushing Data\r
220    // to DirectShow\r
221    if (hres=dsgraphbuilder->AddFilter(sourcefilter,L"Vomp Win Source Filter")!=S_OK) {\r
222    Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Vomp Source Filter!");\r
223      CleanupDS();\r
224      ReleaseMutex(filtermutex);\r
225      return 0;\r
226    }\r
227    //if (audioon) {\r
228      if (hres=dsgraphbuilder->Render(sourcefilter->GetPin(0)/*audio*/)!=S_OK) {\r
229      Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering audio!");\r
230        CleanupDS();\r
231        ReleaseMutex(filtermutex);\r
232        return 0;\r
233      }\r
234    //}\r
235 #ifdef DO_VIDEO\r
236     if (videoon) {\r
237     //We alloc the vmr9 as next step\r
238     if (hres=CoCreateInstance(CLSID_VideoMixingRenderer9,0,\r
239       CLSCTX_INPROC_SERVER,IID_IBaseFilter,(void**) &dsvmrrenderer)!=S_OK) {\r
240       Log::getInstance()->log("VideoWin", Log::WARN ,"Failed creating VMR9 renderer!");\r
241       CleanupDS();\r
242       ReleaseMutex(filtermutex);\r
243     }\r
244       /*VMR 9 stuff**/\r
245     if (hres=dsgraphbuilder->AddFilter(dsvmrrenderer,L"VMR9")!=S_OK) {\r
246       CleanupDS();\r
247       Log::getInstance()->log("VideoWin", Log::WARN ,"Failed adding VMR9 renderer!");\r
248       ReleaseMutex(filtermutex);\r
249       return 0;\r
250     }\r
251     IVMRFilterConfig9* vmrfilconfig;\r
252     if (dsvmrrenderer->QueryInterface(IID_IVMRFilterConfig9,(void**)&vmrfilconfig)!=S_OK) {\r
253       CleanupDS();\r
254       Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Filterconfig interface!");\r
255       ReleaseMutex(filtermutex);\r
256       return 0;\r
257     }\r
258     vmrfilconfig->SetRenderingMode(VMR9Mode_Renderless);\r
259     vmrfilconfig->Release();\r
260 \r
261     if (dsvmrrenderer->QueryInterface(IID_IVMRSurfaceAllocatorNotify9,(void**)& dsvmrsurfnotify)!=S_OK) {\r
262       CleanupDS();\r
263       Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Surface Allocator interface!");\r
264       ReleaseMutex(filtermutex);\r
265       return 0;\r
266     }\r
267     allocatorvmr=new DsAllocator();\r
268     dsvmrsurfnotify->AdviseSurfaceAllocator(NULL,allocatorvmr);\r
269     allocatorvmr->AdviseNotify(dsvmrsurfnotify);\r
270 \r
271 \r
272 \r
273     /*VMR 9 stuff end */\r
274     IFilterGraph2*fg2=NULL;\r
275     if (dsgraphbuilder->QueryInterface(IID_IFilterGraph2,(void**)&fg2)!=S_OK) {\r
276       Log::getInstance()->log("VideoWin", Log::WARN , "Failed querying for FilterGraph2 Interface!");\r
277       CleanupDS();\r
278       ReleaseMutex(filtermutex);\r
279       return 0;\r
280     }\r
281     if (hres=fg2->RenderEx(sourcefilter->GetPin(1)/*video*/,\r
282         AM_RENDEREX_RENDERTOEXISTINGRENDERERS,NULL)!=S_OK) {\r
283       Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering Video!");\r
284       CleanupDS();\r
285       ReleaseMutex(filtermutex);\r
286       return 0;\r
287     }\r
288    }\r
289 #endif\r
290    if (hres=CoCreateInstance(CLSID_SystemClock,NULL,CLSCTX_INPROC_SERVER,\r
291     IID_IReferenceClock,(void**)&dsrefclock)!=S_OK) {\r
292       return 0;\r
293    }\r
294 \r
295    dsgraphbuilder->QueryInterface(IID_IMediaFilter,(void **) &dsmediafilter);\r
296    dsmediafilter->SetSyncSource(dsrefclock);\r
297 \r
298    dsgraphbuilder->QueryInterface(IID_IMediaControl,(void **) &dsmediacontrol);\r
299    dsgraphbuilder->QueryInterface(IID_IBasicAudio,(void **) &dsbasicaudio);     \r
300 \r
301    dsmediacontrol->Run();\r
302    ReleaseMutex(filtermutex);\r
303   return 1;\r
304 }\r
305 \r
306 int VideoWin::stop()\r
307 {\r
308   if (!initted) return 0;\r
309 \r
310   CleanupDS();\r
311 \r
312 \r
313   return 1;\r
314 }\r
315 \r
316 int VideoWin::reset()\r
317 {\r
318   if (!initted) return 0;\r
319   videoposx=0;\r
320   videoposy=0;\r
321   CleanupDS();\r
322 \r
323   return 1;\r
324 }\r
325 \r
326 int VideoWin::pause()\r
327 {\r
328   if (!initted) return 0;\r
329   if (dsmediacontrol) dsmediacontrol->Pause();\r
330   return 1;\r
331 }\r
332 \r
333 int VideoWin::unPause() // FIXME get rid - same as play!!\r
334 {//No on windows this is not the same, I don't get rid of!\r
335   if (!initted) return 0;\r
336   if (dsmediacontrol) dsmediacontrol->Run();\r
337   return 1;\r
338 }\r
339 \r
340 int VideoWin::fastForward()\r
341 {\r
342   if (!initted) return 0;\r
343 \r
344   return 1;\r
345 }\r
346 \r
347 int VideoWin::unFastForward()\r
348 {\r
349   if (!initted) return 0;\r
350   \r
351   return 1;\r
352 }\r
353 \r
354 int VideoWin::attachFrameBuffer()\r
355 {\r
356   if (!initted) return 0;\r
357   return 1;\r
358 }\r
359 \r
360 int VideoWin::blank(void)\r
361 {\r
362   ((OsdWin*)Osd::getInstance())->Blank();\r
363   return 1;\r
364 }\r
365 \r
366 ULLONG VideoWin::getCurrentTimestamp()\r
367 {\r
368         REFERENCE_TIME startoffset;\r
369         REFERENCE_TIME ncr_time;\r
370 \r
371   if (!dsrefclock || !sourcefilter) return 0;\r
372         FILTER_STATE state;\r
373         sourcefilter->GetState(10,&state);\r
374 \r
375         if (state==State_Running) dsrefclock->GetTime(&cr_time);\r
376         ncr_time=cr_time;\r
377   startoffset=sourcefilter->getStartOffset();\r
378         ncr_time-=startoffset;\r
379         ncr_time-=lastreftimeRT;\r
380  /* ULLONG result=frameNumberToTimecode(\r
381     VDR::getInstance()->frameNumberFromPosition(lastreftimeBYTE));*/\r
382         ULLONG result=lastreftimePTS;\r
383         result+=(ULLONG)(ncr_time/10000LL*90LL);\r
384   return result;\r
385 \r
386 }\r
387 \r
388 ULONG VideoWin::timecodeToFrameNumber(ULLONG timecode)\r
389 {\r
390   if (format == PAL) return (ULONG)(((double)timecode / (double)90000) * (double)25);\r
391   else               return (ULONG)(((double)timecode / (double)90000) * (double)30);\r
392 }\r
393 \r
394 ULLONG VideoWin::frameNumberToTimecode(ULONG framenumber)\r
395 {\r
396   if (format == PAL) return (ULLONG)(((double)framenumber * (double)90000) / (double)25);\r
397   else               return (ULLONG)(((double)framenumber * (double)90000) / (double)30);\r
398 }\r
399 \r
400 void VideoWin::CleanupDS()\r
401 {\r
402   WaitForSingleObject(filtermutex,INFINITE);\r
403   if (cur_audio_media_sample) {\r
404     cur_audio_media_sample->Release();\r
405     cur_audio_media_sample=NULL;\r
406   }\r
407   if (cur_video_media_sample) {\r
408     cur_video_media_sample->Release();\r
409     cur_video_media_sample=NULL;\r
410   }\r
411   if (dsbasicaudio) {\r
412           dsbasicaudio->Release();\r
413           dsbasicaudio=NULL;\r
414   }\r
415   if (dsvmrsurfnotify) {\r
416     dsvmrsurfnotify->Release();\r
417     dsvmrsurfnotify=NULL;\r
418   }\r
419   if (dsvmrrenderer) {\r
420     dsvmrrenderer->Release();\r
421     dsvmrrenderer=NULL;\r
422   }\r
423 \r
424   if (allocatorvmr) {\r
425     allocatorvmr->Release();\r
426     allocatorvmr=NULL;\r
427   }\r
428 \r
429   if (dsrefclock) {\r
430     dsrefclock->Release();\r
431     dsrefclock=NULL;\r
432   }\r
433   if (dsmediafilter) {\r
434     dsmediafilter->Release();\r
435     dsmediafilter=NULL;\r
436   }\r
437 \r
438 \r
439   if (dsmediacontrol) {\r
440     dsmediacontrol->Stop();\r
441     dsmediacontrol->Release();\r
442     dsmediacontrol=NULL;\r
443   }\r
444   if (dsgraphbuilder){\r
445 #ifdef DS_DEBUG\r
446     RemoveFromRot(graphidentifier);\r
447 #endif\r
448     dsgraphbuilder->Release();\r
449     dsgraphbuilder=NULL;\r
450     sourcefilter=NULL; //The Graph Builder destroys our SourceFilter\r
451   }\r
452   ReleaseMutex(filtermutex);\r
453 \r
454 }\r
455 \r
456 \r
457 UINT VideoWin::DeliverMediaSample(MediaPacket packet,\r
458      UCHAR* buffer,\r
459      UINT *samplepos)\r
460 {\r
461   /*First Check, if we have an audio sample*/\r
462 #ifdef DO_VIDEO\r
463   /*First Check, if we have an audio sample*/\r
464 \r
465   IMediaSample* ms=NULL;\r
466   REFERENCE_TIME reftime1=0;\r
467   REFERENCE_TIME reftime2=0;\r
468 \r
469   UINT headerstrip=0;\r
470   if (packet.disconti) {\r
471     firstsynched=false;\r
472     DeliverVideoMediaSample();\r
473 \r
474   }\r
475 \r
476 \r
477   /*Inspect PES-Header */\r
478 \r
479   if (*samplepos==0) {//stripheader\r
480     headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/;\r
481     *samplepos+=headerstrip;\r
482     if ( packet.synched ) {\r
483       DeliverVideoMediaSample();//write out old data\r
484    /*   if (packet.presentation_time<0) { //Preroll?\r
485         *samplepos=packet.length;//if we have not processed at least one\r
486         return packet.length;//synched packet ignore it!\r
487       }*/\r
488 \r
489       reftime1=packet.presentation_time;\r
490       reftime2=reftime1+1;\r
491       firstsynched=true;\r
492     } else {\r
493       if (!firstsynched) {//\r
494         *samplepos=packet.length;//if we have not processed at least one\r
495         return packet.length;//synched packet ignore it!\r
496       }\r
497     }\r
498   }\r
499   BYTE *ms_buf;\r
500   UINT ms_length;\r
501   UINT ms_pos;\r
502   UINT haveToCopy;\r
503   if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample\r
504     samplepos=0;\r
505     MILLISLEEP(10);\r
506     return 0;\r
507   }\r
508   ms_pos=ms->GetActualDataLength();\r
509   ms_length=ms->GetSize();\r
510   haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);\r
511   if ((ms_length-ms_pos)<1) {\r
512     DeliverVideoMediaSample(); //we are full!\r
513     if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample\r
514       samplepos=0;\r
515       MILLISLEEP(10);\r
516       return 0;\r
517     }\r
518     ms_pos=ms->GetActualDataLength();\r
519     ms_length=ms->GetSize();\r
520     haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);\r
521   }\r
522   ms->GetPointer(&ms_buf);\r
523 \r
524 \r
525   if (ms_pos==0) {//will only be changed on first packet\r
526     if (packet.disconti) {\r
527       ms->SetDiscontinuity(TRUE);\r
528     } else {\r
529       ms->SetDiscontinuity(FALSE);\r
530     }\r
531     if (packet.synched) {\r
532       ms->SetSyncPoint(TRUE);\r
533       ms->SetTime(&reftime1,&reftime2);\r
534       //ms->SetTime(NULL,NULL);\r
535       ms->SetMediaTime(NULL, NULL);\r
536     if (reftime1<0) ms->SetPreroll(TRUE);\r
537     else ms->SetPreroll(FALSE);\r
538     /*Timecode handling*/\r
539     lastreftimeRT=reftime1;\r
540         lastreftimePTS=packet.pts;\r
541 \r
542     }else {\r
543       ms->SetSyncPoint(FALSE);\r
544       ms->SetTime(NULL,NULL);\r
545       ms->SetMediaTime(NULL, NULL);\r
546     ms->SetPreroll(FALSE);\r
547 \r
548     //  ms->SetSyncPoint(TRUE);\r
549     }\r
550   }\r
551 \r
552 \r
553   memcpy(ms_buf+ms_pos,buffer+packet.pos_buffer+*samplepos,haveToCopy);\r
554     ms->SetActualDataLength(haveToCopy+ms_pos);\r
555 \r
556   *samplepos+=haveToCopy;\r
557 \r
558   return haveToCopy+headerstrip;\r
559 \r
560 #else\r
561 \r
562        *samplepos+=packet.length;\r
563       MILLISLEEP(0); //yet not implemented//bad idea\r
564        return packet.length;\r
565 #endif\r
566 }\r
567 \r
568 int VideoWin::getCurrentAudioMediaSample(IMediaSample** ms)\r
569 {\r
570   //WaitForSingleObject(filtermutex,INFINITE);\r
571   if (!sourcefilter){\r
572   //  ReleaseMutex(filtermutex);\r
573     return 0;\r
574   }\r
575   if (cur_audio_media_sample) {\r
576     *ms=cur_audio_media_sample;//already open\r
577     return 1;\r
578   }\r
579   if (!sourcefilter->getCurrentAudioMediaSample(ms)) {\r
580   //  ReleaseMutex(filtermutex);\r
581   }\r
582   if (*ms) (*ms)->SetActualDataLength(0);\r
583   cur_audio_media_sample=*ms;\r
584   //Don't release the mutex before deliver\r
585   return 1;\r
586 }\r
587 \r
588 int VideoWin::getCurrentVideoMediaSample(IMediaSample** ms)\r
589 {\r
590   //WaitForSingleObject(filtermutex,INFINITE);\r
591   if (!sourcefilter){\r
592   //  ReleaseMutex(filtermutex);\r
593     return 0;\r
594   }\r
595   if (cur_video_media_sample) {\r
596     *ms=cur_video_media_sample;//already open\r
597     return 1;\r
598   }\r
599   if (!sourcefilter->getCurrentVideoMediaSample(ms)) {\r
600   //  ReleaseMutex(filtermutex);\r
601   }\r
602   if (*ms) (*ms)->SetActualDataLength(0);\r
603 \r
604   cur_video_media_sample=*ms;\r
605   //Don't release the mutex before deliver\r
606   return 1;\r
607 }\r
608 \r
609 int VideoWin::DeliverAudioMediaSample(){\r
610   if (cur_audio_media_sample) {\r
611     sourcefilter->DeliverAudioMediaSample(cur_audio_media_sample);\r
612     cur_audio_media_sample=NULL;\r
613   }\r
614   //ReleaseMutex(filtermutex);\r
615   return 1;\r
616 }\r
617 \r
618 int VideoWin::DeliverVideoMediaSample(){\r
619   if (cur_video_media_sample) {\r
620     sourcefilter->DeliverVideoMediaSample(cur_video_media_sample);\r
621     cur_video_media_sample=NULL;\r
622   }\r
623   //ReleaseMutex(filtermutex);\r
624   return 1;\r
625 }\r
626 \r
627 long long VideoWin::SetStartOffset(long long curreftime, bool *rsync)\r
628 {\r
629   *rsync=false;\r
630   if (offsetnotset) {\r
631     startoffset=curreftime;//offset is set for audio\r
632     offsetnotset=false;\r
633     offsetvideonotset=false;\r
634 \r
635 \r
636   } else {\r
637     if (offsetvideonotset) {\r
638       offsetvideonotset=false;\r
639       *rsync=true;\r
640     } else {\r
641       if ( (curreftime-lastrefvideotime)>10000000LL\r
642         || (curreftime-lastrefvideotime)<-10000000LL) {//if pts jumps to big resync\r
643         startoffset+=curreftime-lastrefvideotime;\r
644         lastrefaudiotime+=curreftime-lastrefvideotime;\r
645         //*rsync=true;\r
646         offsetaudionotset=true;\r
647 \r
648       }\r
649     }\r
650 \r
651   }\r
652 \r
653   lastrefvideotime=curreftime;\r
654   \r
655   return startoffset;\r
656 \r
657 }\r
658 \r
659 long long VideoWin::SetStartAudioOffset(long long curreftime, bool *rsync)\r
660 {\r
661   *rsync=false;\r
662   if (offsetnotset) {\r
663     startoffset=curreftime;\r
664     offsetnotset=false;\r
665     offsetaudionotset=false;\r
666   }else {\r
667     if (offsetaudionotset) {\r
668       offsetaudionotset=false;\r
669       *rsync=true;\r
670     } else {\r
671       if ( (curreftime-lastrefaudiotime)>10000000LL\r
672         || (curreftime-lastrefaudiotime)<-10000000LL) {//if pts jumps to big resync\r
673         startoffset+=curreftime-lastrefaudiotime;\r
674         lastrefvideotime+=curreftime-lastrefaudiotime;\r
675         //*rsync=true;\r
676         offsetvideonotset=true;\r
677 \r
678       }\r
679     }\r
680 \r
681   }\r
682   lastrefaudiotime=curreftime;\r
683   return startoffset;\r
684 \r
685 }\r
686 void VideoWin::ResetTimeOffsets() {\r
687   offsetnotset=true; //called from demuxer\r
688   offsetvideonotset=true;\r
689   offsetaudionotset=true;\r
690   startoffset=0;\r
691   lastrefaudiotime=0;\r
692   lastrefvideotime=0;\r
693   lastreftimeRT=0;\r
694   lastreftimePTS=0;\r
695 \r
696 \r
697 }\r
698 \r
699 void VideoWin::SetAudioVolume(long volume)\r
700 {\r
701         if (dsbasicaudio) dsbasicaudio->put_Volume(volume);\r
702 }\r
703 \r
704 #ifdef DEV\r
705 int VideoWin::test()\r
706 {\r
707   return 0;\r
708 }\r
709 \r
710 int VideoWin::test2()\r
711 {\r
712   return 0;\r
713 }\r
714 #endif\r
715 \r