]> git.vomp.tv Git - vompclient.git/blob - videowin.cc
Fixes (1) for new frame number navigation
[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   lastreftimeBYTE=0;\r
52   lastreftimeRT=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         result+=(ULLONG)(ncr_time/10000LL*90LL);\r
383   return result;\r
384 \r
385 }\r
386 \r
387 ULONG VideoWin::timecodeToFrameNumber(ULLONG timecode)\r
388 {\r
389   if (format == PAL) return (ULONG)(((double)timecode / (double)90000) * (double)25);\r
390   else               return (ULONG)(((double)timecode / (double)90000) * (double)30);\r
391 }\r
392 \r
393 ULLONG VideoWin::frameNumberToTimecode(ULONG framenumber)\r
394 {\r
395   if (format == PAL) return (ULLONG)(((double)framenumber * (double)90000) / (double)25);\r
396   else               return (ULLONG)(((double)framenumber * (double)90000) / (double)30);\r
397 }\r
398 \r
399 void VideoWin::CleanupDS()\r
400 {\r
401   WaitForSingleObject(filtermutex,INFINITE);\r
402   if (cur_audio_media_sample) {\r
403     cur_audio_media_sample->Release();\r
404     cur_audio_media_sample=NULL;\r
405   }\r
406   if (cur_video_media_sample) {\r
407     cur_video_media_sample->Release();\r
408     cur_video_media_sample=NULL;\r
409   }\r
410   if (dsbasicaudio) {\r
411           dsbasicaudio->Release();\r
412           dsbasicaudio=NULL;\r
413   }\r
414   if (dsvmrsurfnotify) {\r
415     dsvmrsurfnotify->Release();\r
416     dsvmrsurfnotify=NULL;\r
417   }\r
418   if (dsvmrrenderer) {\r
419     dsvmrrenderer->Release();\r
420     dsvmrrenderer=NULL;\r
421   }\r
422 \r
423   if (allocatorvmr) {\r
424     allocatorvmr->Release();\r
425     allocatorvmr=NULL;\r
426   }\r
427 \r
428   if (dsrefclock) {\r
429     dsrefclock->Release();\r
430     dsrefclock=NULL;\r
431   }\r
432   if (dsmediafilter) {\r
433     dsmediafilter->Release();\r
434     dsmediafilter=NULL;\r
435   }\r
436 \r
437 \r
438   if (dsmediacontrol) {\r
439     dsmediacontrol->Stop();\r
440     dsmediacontrol->Release();\r
441     dsmediacontrol=NULL;\r
442   }\r
443   if (dsgraphbuilder){\r
444 #ifdef DS_DEBUG\r
445     RemoveFromRot(graphidentifier);\r
446 #endif\r
447     dsgraphbuilder->Release();\r
448     dsgraphbuilder=NULL;\r
449     sourcefilter=NULL; //The Graph Builder destroys our SourceFilter\r
450   }\r
451   ReleaseMutex(filtermutex);\r
452 \r
453 }\r
454 \r
455 \r
456 UINT VideoWin::DeliverMediaSample(MediaPacket packet,\r
457      UCHAR* buffer,\r
458      UINT *samplepos)\r
459 {\r
460   /*First Check, if we have an audio sample*/\r
461 #ifdef DO_VIDEO\r
462   /*First Check, if we have an audio sample*/\r
463 \r
464   IMediaSample* ms=NULL;\r
465   REFERENCE_TIME reftime1=0;\r
466   REFERENCE_TIME reftime2=0;\r
467 \r
468   UINT headerstrip=0;\r
469   if (packet.disconti) {\r
470     firstsynched=false;\r
471     DeliverVideoMediaSample();\r
472 \r
473   }\r
474 \r
475 \r
476   /*Inspect PES-Header */\r
477 \r
478   if (*samplepos==0) {//stripheader\r
479     headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/;\r
480     *samplepos+=headerstrip;\r
481     if ( packet.synched ) {\r
482       DeliverVideoMediaSample();//write out old data\r
483    /*   if (packet.presentation_time<0) { //Preroll?\r
484         *samplepos=packet.length;//if we have not processed at least one\r
485         return packet.length;//synched packet ignore it!\r
486       }*/\r
487 \r
488       reftime1=packet.presentation_time;\r
489       reftime2=reftime1+1;\r
490       firstsynched=true;\r
491     } else {\r
492       if (!firstsynched) {//\r
493         *samplepos=packet.length;//if we have not processed at least one\r
494         return packet.length;//synched packet ignore it!\r
495       }\r
496     }\r
497   }\r
498   BYTE *ms_buf;\r
499   UINT ms_length;\r
500   UINT ms_pos;\r
501   UINT haveToCopy;\r
502   if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample\r
503     samplepos=0;\r
504     MILLISLEEP(10);\r
505     return 0;\r
506   }\r
507   ms_pos=ms->GetActualDataLength();\r
508   ms_length=ms->GetSize();\r
509   haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);\r
510   if ((ms_length-ms_pos)<1) {\r
511     DeliverVideoMediaSample(); //we are full!\r
512     if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample\r
513       samplepos=0;\r
514       MILLISLEEP(10);\r
515       return 0;\r
516     }\r
517     ms_pos=ms->GetActualDataLength();\r
518     ms_length=ms->GetSize();\r
519     haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);\r
520   }\r
521   ms->GetPointer(&ms_buf);\r
522 \r
523 \r
524   if (ms_pos==0) {//will only be changed on first packet\r
525     if (packet.disconti) {\r
526       ms->SetDiscontinuity(TRUE);\r
527     } else {\r
528       ms->SetDiscontinuity(FALSE);\r
529     }\r
530     if (packet.synched) {\r
531       ms->SetSyncPoint(TRUE);\r
532       ms->SetTime(&reftime1,&reftime2);\r
533       //ms->SetTime(NULL,NULL);\r
534       ms->SetMediaTime(NULL, NULL);\r
535     if (reftime1<0) ms->SetPreroll(TRUE);\r
536     else ms->SetPreroll(FALSE);\r
537     /*Timecode handling*/\r
538     lastreftimeRT=reftime1;\r
539     lastreftimeBYTE=packet.recording_byte_pos;\r
540 \r
541     }else {\r
542       ms->SetSyncPoint(FALSE);\r
543       ms->SetTime(NULL,NULL);\r
544       ms->SetMediaTime(NULL, NULL);\r
545     ms->SetPreroll(FALSE);\r
546 \r
547     //  ms->SetSyncPoint(TRUE);\r
548     }\r
549   }\r
550 \r
551 \r
552   memcpy(ms_buf+ms_pos,buffer+packet.pos_buffer+*samplepos,haveToCopy);\r
553     ms->SetActualDataLength(haveToCopy+ms_pos);\r
554 \r
555   *samplepos+=haveToCopy;\r
556 \r
557   return haveToCopy+headerstrip;\r
558 \r
559 #else\r
560 \r
561        *samplepos+=packet.length;\r
562       MILLISLEEP(0); //yet not implemented//bad idea\r
563        return packet.length;\r
564 #endif\r
565 }\r
566 \r
567 int VideoWin::getCurrentAudioMediaSample(IMediaSample** ms)\r
568 {\r
569   //WaitForSingleObject(filtermutex,INFINITE);\r
570   if (!sourcefilter){\r
571   //  ReleaseMutex(filtermutex);\r
572     return 0;\r
573   }\r
574   if (cur_audio_media_sample) {\r
575     *ms=cur_audio_media_sample;//already open\r
576     return 1;\r
577   }\r
578   if (!sourcefilter->getCurrentAudioMediaSample(ms)) {\r
579   //  ReleaseMutex(filtermutex);\r
580   }\r
581   if (*ms) (*ms)->SetActualDataLength(0);\r
582   cur_audio_media_sample=*ms;\r
583   //Don't release the mutex before deliver\r
584   return 1;\r
585 }\r
586 \r
587 int VideoWin::getCurrentVideoMediaSample(IMediaSample** ms)\r
588 {\r
589   //WaitForSingleObject(filtermutex,INFINITE);\r
590   if (!sourcefilter){\r
591   //  ReleaseMutex(filtermutex);\r
592     return 0;\r
593   }\r
594   if (cur_video_media_sample) {\r
595     *ms=cur_video_media_sample;//already open\r
596     return 1;\r
597   }\r
598   if (!sourcefilter->getCurrentVideoMediaSample(ms)) {\r
599   //  ReleaseMutex(filtermutex);\r
600   }\r
601   if (*ms) (*ms)->SetActualDataLength(0);\r
602 \r
603   cur_video_media_sample=*ms;\r
604   //Don't release the mutex before deliver\r
605   return 1;\r
606 }\r
607 \r
608 int VideoWin::DeliverAudioMediaSample(){\r
609   if (cur_audio_media_sample) {\r
610     sourcefilter->DeliverAudioMediaSample(cur_audio_media_sample);\r
611     cur_audio_media_sample=NULL;\r
612   }\r
613   //ReleaseMutex(filtermutex);\r
614   return 1;\r
615 }\r
616 \r
617 int VideoWin::DeliverVideoMediaSample(){\r
618   if (cur_video_media_sample) {\r
619     sourcefilter->DeliverVideoMediaSample(cur_video_media_sample);\r
620     cur_video_media_sample=NULL;\r
621   }\r
622   //ReleaseMutex(filtermutex);\r
623   return 1;\r
624 }\r
625 \r
626 long long VideoWin::SetStartOffset(long long curreftime, bool *rsync)\r
627 {\r
628   *rsync=false;\r
629   if (offsetnotset) {\r
630     startoffset=curreftime;//offset is set for audio\r
631     offsetnotset=false;\r
632     offsetvideonotset=false;\r
633 \r
634 \r
635   } else {\r
636     if (offsetvideonotset) {\r
637       offsetvideonotset=false;\r
638       *rsync=true;\r
639     } else {\r
640       if ( (curreftime-lastrefvideotime)>10000000LL\r
641         || (curreftime-lastrefvideotime)<-10000000LL) {//if pts jumps to big resync\r
642         startoffset+=curreftime-lastrefvideotime;\r
643         lastrefaudiotime+=curreftime-lastrefvideotime;\r
644         //*rsync=true;\r
645         offsetaudionotset=true;\r
646 \r
647       }\r
648     }\r
649 \r
650   }\r
651 \r
652   lastrefvideotime=curreftime;\r
653   \r
654   return startoffset;\r
655 \r
656 }\r
657 \r
658 long long VideoWin::SetStartAudioOffset(long long curreftime, bool *rsync)\r
659 {\r
660   *rsync=false;\r
661   if (offsetnotset) {\r
662     startoffset=curreftime;\r
663     offsetnotset=false;\r
664     offsetaudionotset=false;\r
665   }else {\r
666     if (offsetaudionotset) {\r
667       offsetaudionotset=false;\r
668       *rsync=true;\r
669     } else {\r
670       if ( (curreftime-lastrefaudiotime)>10000000LL\r
671         || (curreftime-lastrefaudiotime)<-10000000LL) {//if pts jumps to big resync\r
672         startoffset+=curreftime-lastrefaudiotime;\r
673         lastrefvideotime+=curreftime-lastrefaudiotime;\r
674         //*rsync=true;\r
675         offsetvideonotset=true;\r
676 \r
677       }\r
678     }\r
679 \r
680   }\r
681   lastrefaudiotime=curreftime;\r
682   return startoffset;\r
683 \r
684 }\r
685 void VideoWin::ResetTimeOffsets() {\r
686   offsetnotset=true; //called from demuxer\r
687   offsetvideonotset=true;\r
688   offsetaudionotset=true;\r
689   startoffset=0;\r
690   lastrefaudiotime=0;\r
691   lastrefvideotime=0;\r
692   lastreftimeBYTE=0;\r
693   lastreftimeRT=0;\r
694 \r
695 \r
696 }\r
697 \r
698 void VideoWin::SetAudioVolume(long volume)\r
699 {\r
700         if (dsbasicaudio) dsbasicaudio->put_Volume(volume);\r
701 }\r
702 \r
703 #ifdef DEV\r
704 int VideoWin::test()\r
705 {\r
706   return 0;\r
707 }\r
708 \r
709 int VideoWin::test2()\r
710 {\r
711   return 0;\r
712 }\r
713 #endif\r
714 \r