]> git.vomp.tv Git - vompclient.git/blob - videowin.cc
MVP/Windows convergence: Stream; DrainTarget
[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 void VideoWin::PrepareMediaSample(const MediaPacketList& mplist,\r
457      UINT samplepos)\r
458 {\r
459   mediapacket = mplist.front();\r
460 }\r
461 \r
462 UINT VideoWin::DeliverMediaSample(const UCHAR* buffer, UINT *samplepos)\r
463 {\r
464   DeliverMediaPacket(mediapacket, buffer, samplepos);\r
465   if (*samplepos == mediapacket.length) {\r
466     *samplepos = 0;\r
467     return 1;\r
468   }\r
469   else return 0;\r
470 }\r
471 \r
472 UINT VideoWin::DeliverMediaPacket(MediaPacket packet,\r
473      const UCHAR* buffer,\r
474      UINT *samplepos)\r
475 {\r
476   /*First Check, if we have an audio sample*/\r
477 #ifdef DO_VIDEO\r
478   /*First Check, if we have an audio sample*/\r
479 \r
480   IMediaSample* ms=NULL;\r
481   REFERENCE_TIME reftime1=0;\r
482   REFERENCE_TIME reftime2=0;\r
483 \r
484   UINT headerstrip=0;\r
485   if (packet.disconti) {\r
486     firstsynched=false;\r
487     DeliverVideoMediaSample();\r
488 \r
489   }\r
490 \r
491 \r
492   /*Inspect PES-Header */\r
493 \r
494   if (*samplepos==0) {//stripheader\r
495     headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/;\r
496     *samplepos+=headerstrip;\r
497     if ( packet.synched ) {\r
498       DeliverVideoMediaSample();//write out old data\r
499    /*   if (packet.presentation_time<0) { //Preroll?\r
500         *samplepos=packet.length;//if we have not processed at least one\r
501         return packet.length;//synched packet ignore it!\r
502       }*/\r
503 \r
504       reftime1=packet.presentation_time;\r
505       reftime2=reftime1+1;\r
506       firstsynched=true;\r
507     } else {\r
508       if (!firstsynched) {//\r
509         *samplepos=packet.length;//if we have not processed at least one\r
510         return packet.length;//synched packet ignore it!\r
511       }\r
512     }\r
513   }\r
514   BYTE *ms_buf;\r
515   UINT ms_length;\r
516   UINT ms_pos;\r
517   UINT haveToCopy;\r
518   if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample\r
519     samplepos=0;\r
520     MILLISLEEP(10);\r
521     return 0;\r
522   }\r
523   ms_pos=ms->GetActualDataLength();\r
524   ms_length=ms->GetSize();\r
525   haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);\r
526   if ((ms_length-ms_pos)<1) {\r
527     DeliverVideoMediaSample(); //we are full!\r
528     if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample\r
529       samplepos=0;\r
530       MILLISLEEP(10);\r
531       return 0;\r
532     }\r
533     ms_pos=ms->GetActualDataLength();\r
534     ms_length=ms->GetSize();\r
535     haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);\r
536   }\r
537   ms->GetPointer(&ms_buf);\r
538 \r
539 \r
540   if (ms_pos==0) {//will only be changed on first packet\r
541     if (packet.disconti) {\r
542       ms->SetDiscontinuity(TRUE);\r
543     } else {\r
544       ms->SetDiscontinuity(FALSE);\r
545     }\r
546     if (packet.synched) {\r
547       ms->SetSyncPoint(TRUE);\r
548       ms->SetTime(&reftime1,&reftime2);\r
549       //ms->SetTime(NULL,NULL);\r
550       ms->SetMediaTime(NULL, NULL);\r
551     if (reftime1<0) ms->SetPreroll(TRUE);\r
552     else ms->SetPreroll(FALSE);\r
553     /*Timecode handling*/\r
554     lastreftimeRT=reftime1;\r
555         lastreftimePTS=packet.pts;\r
556 \r
557     }else {\r
558       ms->SetSyncPoint(FALSE);\r
559       ms->SetTime(NULL,NULL);\r
560       ms->SetMediaTime(NULL, NULL);\r
561     ms->SetPreroll(FALSE);\r
562 \r
563     //  ms->SetSyncPoint(TRUE);\r
564     }\r
565   }\r
566 \r
567 \r
568   memcpy(ms_buf+ms_pos,buffer+packet.pos_buffer+*samplepos,haveToCopy);\r
569     ms->SetActualDataLength(haveToCopy+ms_pos);\r
570 \r
571   *samplepos+=haveToCopy;\r
572 \r
573   return haveToCopy+headerstrip;\r
574 \r
575 #else\r
576 \r
577        *samplepos+=packet.length;\r
578       MILLISLEEP(0); //yet not implemented//bad idea\r
579        return packet.length;\r
580 #endif\r
581 }\r
582 \r
583 int VideoWin::getCurrentAudioMediaSample(IMediaSample** ms)\r
584 {\r
585   //WaitForSingleObject(filtermutex,INFINITE);\r
586   if (!sourcefilter){\r
587   //  ReleaseMutex(filtermutex);\r
588     return 0;\r
589   }\r
590   if (cur_audio_media_sample) {\r
591     *ms=cur_audio_media_sample;//already open\r
592     return 1;\r
593   }\r
594   if (!sourcefilter->getCurrentAudioMediaSample(ms)) {\r
595   //  ReleaseMutex(filtermutex);\r
596   }\r
597   if (*ms) (*ms)->SetActualDataLength(0);\r
598   cur_audio_media_sample=*ms;\r
599   //Don't release the mutex before deliver\r
600   return 1;\r
601 }\r
602 \r
603 int VideoWin::getCurrentVideoMediaSample(IMediaSample** ms)\r
604 {\r
605   //WaitForSingleObject(filtermutex,INFINITE);\r
606   if (!sourcefilter){\r
607   //  ReleaseMutex(filtermutex);\r
608     return 0;\r
609   }\r
610   if (cur_video_media_sample) {\r
611     *ms=cur_video_media_sample;//already open\r
612     return 1;\r
613   }\r
614   if (!sourcefilter->getCurrentVideoMediaSample(ms)) {\r
615   //  ReleaseMutex(filtermutex);\r
616   }\r
617   if (*ms) (*ms)->SetActualDataLength(0);\r
618 \r
619   cur_video_media_sample=*ms;\r
620   //Don't release the mutex before deliver\r
621   return 1;\r
622 }\r
623 \r
624 int VideoWin::DeliverAudioMediaSample(){\r
625   if (cur_audio_media_sample) {\r
626     sourcefilter->DeliverAudioMediaSample(cur_audio_media_sample);\r
627     cur_audio_media_sample=NULL;\r
628   }\r
629   //ReleaseMutex(filtermutex);\r
630   return 1;\r
631 }\r
632 \r
633 int VideoWin::DeliverVideoMediaSample(){\r
634   if (cur_video_media_sample) {\r
635     sourcefilter->DeliverVideoMediaSample(cur_video_media_sample);\r
636     cur_video_media_sample=NULL;\r
637   }\r
638   //ReleaseMutex(filtermutex);\r
639   return 1;\r
640 }\r
641 \r
642 long long VideoWin::SetStartOffset(long long curreftime, bool *rsync)\r
643 {\r
644   *rsync=false;\r
645   if (offsetnotset) {\r
646     startoffset=curreftime;//offset is set for audio\r
647     offsetnotset=false;\r
648     offsetvideonotset=false;\r
649 \r
650 \r
651   } else {\r
652     if (offsetvideonotset) {\r
653       offsetvideonotset=false;\r
654       *rsync=true;\r
655     } else {\r
656       if ( (curreftime-lastrefvideotime)>10000000LL\r
657         || (curreftime-lastrefvideotime)<-10000000LL) {//if pts jumps to big resync\r
658         startoffset+=curreftime-lastrefvideotime;\r
659         lastrefaudiotime+=curreftime-lastrefvideotime;\r
660         //*rsync=true;\r
661         offsetaudionotset=true;\r
662 \r
663       }\r
664     }\r
665 \r
666   }\r
667 \r
668   lastrefvideotime=curreftime;\r
669   \r
670   return startoffset;\r
671 \r
672 }\r
673 \r
674 long long VideoWin::SetStartAudioOffset(long long curreftime, bool *rsync)\r
675 {\r
676   *rsync=false;\r
677   if (offsetnotset) {\r
678     startoffset=curreftime;\r
679     offsetnotset=false;\r
680     offsetaudionotset=false;\r
681   }else {\r
682     if (offsetaudionotset) {\r
683       offsetaudionotset=false;\r
684       *rsync=true;\r
685     } else {\r
686       if ( (curreftime-lastrefaudiotime)>10000000LL\r
687         || (curreftime-lastrefaudiotime)<-10000000LL) {//if pts jumps to big resync\r
688         startoffset+=curreftime-lastrefaudiotime;\r
689         lastrefvideotime+=curreftime-lastrefaudiotime;\r
690         //*rsync=true;\r
691         offsetvideonotset=true;\r
692 \r
693       }\r
694     }\r
695 \r
696   }\r
697   lastrefaudiotime=curreftime;\r
698   return startoffset;\r
699 \r
700 }\r
701 void VideoWin::ResetTimeOffsets() {\r
702   offsetnotset=true; //called from demuxer\r
703   offsetvideonotset=true;\r
704   offsetaudionotset=true;\r
705   startoffset=0;\r
706   lastrefaudiotime=0;\r
707   lastrefvideotime=0;\r
708   lastreftimeRT=0;\r
709   lastreftimePTS=0;\r
710 \r
711 \r
712 }\r
713 \r
714 void VideoWin::SetAudioVolume(long volume)\r
715 {\r
716         if (dsbasicaudio) dsbasicaudio->put_Volume(volume);\r
717 }\r
718 \r
719 #ifdef DEV\r
720 int VideoWin::test()\r
721 {\r
722   return 0;\r
723 }\r
724 \r
725 int VideoWin::test2()\r
726 {\r
727   return 0;\r
728 }\r
729 #endif\r
730 \r