]> git.vomp.tv Git - vompclient.git/blob - videowin.cc
New code from Marten
[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   return 1;\r
204 }\r
205 \r
206 int VideoWin::dsplay()\r
207 {\r
208   if (!initted) return 0;\r
209 \r
210   //Build filter graph\r
211   HRESULT hres;\r
212 \r
213   if (hres=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,\r
214     IID_IGraphBuilder,(void**)&dsgraphbuilder)!=S_OK) {\r
215       return 0;\r
216    }\r
217    #ifdef DS_DEBUG\r
218    AddToRot(dsgraphbuilder,&graphidentifier);\r
219    #endif\r
220    //This is just a try to see if building the graph works\r
221 //   dsgraphbuilder->RenderFile(L"D:\\Projekte\\VTP Client\\test.mpa" ,NULL);\r
222    //So this is the real code, this prevents the feeder from calling noexisting objects!\r
223    WaitForSingleObject(filtermutex,INFINITE);\r
224    firstsynched=false;\r
225    sourcefilter=new DsSourceFilter(); //Creating our Source filter for pushing Data\r
226    // to DirectShow\r
227    if (hres=dsgraphbuilder->AddFilter(sourcefilter,L"Vomp Win Source Filter")!=S_OK) {\r
228    Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Vomp Source Filter!");\r
229      CleanupDS();\r
230      ReleaseMutex(filtermutex);\r
231      return 0;\r
232    }\r
233    //if (audioon) {\r
234      if (hres=dsgraphbuilder->Render(sourcefilter->GetPin(0)/*audio*/)!=S_OK) {\r
235      Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering audio!");\r
236        CleanupDS();\r
237        ReleaseMutex(filtermutex);\r
238        return 0;\r
239      }\r
240    //}\r
241 #ifdef DO_VIDEO\r
242     if (videoon) {\r
243     //We alloc the vmr9 as next step\r
244     if (hres=CoCreateInstance(CLSID_VideoMixingRenderer9,0,\r
245       CLSCTX_INPROC_SERVER,IID_IBaseFilter,(void**) &dsvmrrenderer)!=S_OK) {\r
246       Log::getInstance()->log("VideoWin", Log::WARN ,"Failed creating VMR9 renderer!");\r
247       CleanupDS();\r
248       ReleaseMutex(filtermutex);\r
249     }\r
250       /*VMR 9 stuff**/\r
251     if (hres=dsgraphbuilder->AddFilter(dsvmrrenderer,L"VMR9")!=S_OK) {\r
252       CleanupDS();\r
253       Log::getInstance()->log("VideoWin", Log::WARN ,"Failed adding VMR9 renderer!");\r
254       ReleaseMutex(filtermutex);\r
255       return 0;\r
256     }\r
257     IVMRFilterConfig9* vmrfilconfig;\r
258     if (dsvmrrenderer->QueryInterface(IID_IVMRFilterConfig9,(void**)&vmrfilconfig)!=S_OK) {\r
259       CleanupDS();\r
260       Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Filterconfig interface!");\r
261       ReleaseMutex(filtermutex);\r
262       return 0;\r
263     }\r
264     vmrfilconfig->SetRenderingMode(VMR9Mode_Renderless);\r
265     vmrfilconfig->Release();\r
266 \r
267     if (dsvmrrenderer->QueryInterface(IID_IVMRSurfaceAllocatorNotify9,(void**)& dsvmrsurfnotify)!=S_OK) {\r
268       CleanupDS();\r
269       Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Surface Allocator interface!");\r
270       ReleaseMutex(filtermutex);\r
271       return 0;\r
272     }\r
273     allocatorvmr=new DsAllocator();\r
274     dsvmrsurfnotify->AdviseSurfaceAllocator(NULL,allocatorvmr);\r
275     allocatorvmr->AdviseNotify(dsvmrsurfnotify);\r
276 \r
277 \r
278 \r
279     /*VMR 9 stuff end */\r
280     IFilterGraph2*fg2=NULL;\r
281     if (dsgraphbuilder->QueryInterface(IID_IFilterGraph2,(void**)&fg2)!=S_OK) {\r
282       Log::getInstance()->log("VideoWin", Log::WARN , "Failed querying for FilterGraph2 Interface!");\r
283       CleanupDS();\r
284       ReleaseMutex(filtermutex);\r
285       return 0;\r
286     }\r
287     if (hres=fg2->RenderEx(sourcefilter->GetPin(1)/*video*/,\r
288         AM_RENDEREX_RENDERTOEXISTINGRENDERERS,NULL)!=S_OK) {\r
289       Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering Video!");\r
290       CleanupDS();\r
291       ReleaseMutex(filtermutex);\r
292       return 0;\r
293     }\r
294    }\r
295 #endif\r
296    if (hres=CoCreateInstance(CLSID_SystemClock,NULL,CLSCTX_INPROC_SERVER,\r
297     IID_IReferenceClock,(void**)&dsrefclock)!=S_OK) {\r
298       return 0;\r
299    }\r
300 \r
301    dsgraphbuilder->QueryInterface(IID_IMediaFilter,(void **) &dsmediafilter);\r
302    dsmediafilter->SetSyncSource(dsrefclock);\r
303 \r
304    dsgraphbuilder->QueryInterface(IID_IMediaControl,(void **) &dsmediacontrol);\r
305    dsgraphbuilder->QueryInterface(IID_IBasicAudio,(void **) &dsbasicaudio);     \r
306 \r
307    dsmediacontrol->Run();\r
308    ReleaseMutex(filtermutex);\r
309   return 1;\r
310 }\r
311 \r
312 int VideoWin::dsstop()\r
313 {\r
314   if (!initted) return 0;\r
315 \r
316   CleanupDS();\r
317 \r
318 \r
319   return 1;\r
320 }\r
321 \r
322 int VideoWin::stop()\r
323 {\r
324   if (!initted) return 0;\r
325 \r
326 \r
327   return 1;\r
328 }\r
329 \r
330 int VideoWin::reset()\r
331 {\r
332   if (!initted) return 0;\r
333   \r
334 \r
335   return 1;\r
336 }\r
337 \r
338 int VideoWin::dsreset()\r
339 {\r
340   if (!initted) return 0;\r
341   videoposx=0;\r
342   videoposy=0;\r
343   CleanupDS();\r
344 \r
345   return 1;\r
346 }\r
347 \r
348 int VideoWin::dspause()\r
349 {\r
350   if (!initted) return 0;\r
351   if (dsmediacontrol) dsmediacontrol->Pause();\r
352   return 1;\r
353 }\r
354 \r
355 int VideoWin::pause()\r
356 {\r
357   if (!initted) return 0;\r
358   \r
359   return 1;\r
360 }\r
361 \r
362 int VideoWin::unPause() // FIXME get rid - same as play!!\r
363 {//No on windows this is not the same, I don't get rid of!\r
364   if (!initted) return 0;\r
365   return 1;\r
366 }\r
367 \r
368 int VideoWin::dsunPause() // FIXME get rid - same as play!!\r
369 {//No on windows this is not the same, I don't get rid of!\r
370   if (!initted) return 0;\r
371   if (dsmediacontrol) dsmediacontrol->Run();\r
372   return 1;\r
373 }\r
374 \r
375 int VideoWin::fastForward()\r
376 {\r
377   if (!initted) return 0;\r
378 \r
379   return 1;\r
380 }\r
381 \r
382 int VideoWin::unFastForward()\r
383 {\r
384   if (!initted) return 0;\r
385   \r
386   return 1;\r
387 }\r
388 \r
389 int VideoWin::attachFrameBuffer()\r
390 {\r
391   if (!initted) return 0;\r
392   return 1;\r
393 }\r
394 \r
395 int VideoWin::blank(void)\r
396 {\r
397   ((OsdWin*)Osd::getInstance())->Blank();\r
398   return 1;\r
399 }\r
400 \r
401 ULLONG VideoWin::getCurrentTimestamp()\r
402 {\r
403         REFERENCE_TIME startoffset;\r
404         REFERENCE_TIME ncr_time;\r
405 \r
406   if (!dsrefclock || !sourcefilter) return 0;\r
407         FILTER_STATE state;\r
408         sourcefilter->GetState(10,&state);\r
409 \r
410         if (state==State_Running) dsrefclock->GetTime(&cr_time);\r
411         ncr_time=cr_time;\r
412   startoffset=sourcefilter->getStartOffset();\r
413         ncr_time-=startoffset;\r
414         ncr_time-=lastreftimeRT;\r
415  /* ULLONG result=frameNumberToTimecode(\r
416     VDR::getInstance()->frameNumberFromPosition(lastreftimeBYTE));*/\r
417         ULLONG result=lastreftimePTS;\r
418         result+=(ULLONG)(ncr_time/10000LL*90LL);\r
419   return result;\r
420 \r
421 }\r
422 \r
423 ULONG VideoWin::timecodeToFrameNumber(ULLONG timecode)\r
424 {\r
425   if (format == PAL) return (ULONG)(((double)timecode / (double)90000) * (double)25);\r
426   else               return (ULONG)(((double)timecode / (double)90000) * (double)30);\r
427 }\r
428 \r
429 ULLONG VideoWin::frameNumberToTimecode(ULONG framenumber)\r
430 {\r
431   if (format == PAL) return (ULLONG)(((double)framenumber * (double)90000) / (double)25);\r
432   else               return (ULLONG)(((double)framenumber * (double)90000) / (double)30);\r
433 }\r
434 \r
435 void VideoWin::CleanupDS()\r
436 {\r
437   WaitForSingleObject(filtermutex,INFINITE);\r
438   if (cur_audio_media_sample) {\r
439     cur_audio_media_sample->Release();\r
440     cur_audio_media_sample=NULL;\r
441   }\r
442   if (cur_video_media_sample) {\r
443     cur_video_media_sample->Release();\r
444     cur_video_media_sample=NULL;\r
445   }\r
446   if (dsbasicaudio) {\r
447           dsbasicaudio->Release();\r
448           dsbasicaudio=NULL;\r
449   }\r
450   if (dsvmrsurfnotify) {\r
451     dsvmrsurfnotify->Release();\r
452     dsvmrsurfnotify=NULL;\r
453   }\r
454   if (dsvmrrenderer) {\r
455     dsvmrrenderer->Release();\r
456     dsvmrrenderer=NULL;\r
457   }\r
458 \r
459   if (allocatorvmr) {\r
460     allocatorvmr->Release();\r
461     allocatorvmr=NULL;\r
462   }\r
463 \r
464   if (dsrefclock) {\r
465     dsrefclock->Release();\r
466     dsrefclock=NULL;\r
467   }\r
468   if (dsmediafilter) {\r
469     dsmediafilter->Release();\r
470     dsmediafilter=NULL;\r
471   }\r
472 \r
473 \r
474   if (dsmediacontrol) {\r
475     dsmediacontrol->Stop();\r
476     dsmediacontrol->Release();\r
477     dsmediacontrol=NULL;\r
478   }\r
479   if (dsgraphbuilder){\r
480 #ifdef DS_DEBUG\r
481     RemoveFromRot(graphidentifier);\r
482 #endif\r
483     dsgraphbuilder->Release();\r
484     dsgraphbuilder=NULL;\r
485     sourcefilter=NULL; //The Graph Builder destroys our SourceFilter\r
486   }\r
487   ReleaseMutex(filtermutex);\r
488 \r
489 }\r
490 \r
491 void VideoWin::PrepareMediaSample(const MediaPacketList& mplist,\r
492      UINT samplepos)\r
493 {\r
494   mediapacket = mplist.front();\r
495 }\r
496 \r
497 UINT VideoWin::DeliverMediaSample(const UCHAR* buffer, UINT *samplepos)\r
498 {\r
499   DeliverMediaPacket(mediapacket, buffer, samplepos);\r
500   if (*samplepos == mediapacket.length) {\r
501     *samplepos = 0;\r
502     return 1;\r
503   }\r
504   else return 0;\r
505 }\r
506 \r
507 UINT VideoWin::DeliverMediaPacket(MediaPacket packet,\r
508      const UCHAR* buffer,\r
509      UINT *samplepos)\r
510 {\r
511   /*First Check, if we have an audio sample*/\r
512 #ifdef DO_VIDEO\r
513   /*First Check, if we have an audio sample*/\r
514 \r
515   IMediaSample* ms=NULL;\r
516   REFERENCE_TIME reftime1=0;\r
517   REFERENCE_TIME reftime2=0;\r
518 \r
519   UINT headerstrip=0;\r
520   if (packet.disconti) {\r
521     firstsynched=false;\r
522     DeliverVideoMediaSample();\r
523 \r
524   }\r
525 \r
526 \r
527   /*Inspect PES-Header */\r
528 \r
529   if (*samplepos==0) {//stripheader\r
530     headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/;\r
531     *samplepos+=headerstrip;\r
532     if ( packet.synched ) {\r
533       DeliverVideoMediaSample();//write out old data\r
534    /*   if (packet.presentation_time<0) { //Preroll?\r
535         *samplepos=packet.length;//if we have not processed at least one\r
536         return packet.length;//synched packet ignore it!\r
537       }*/\r
538 \r
539       reftime1=packet.presentation_time;\r
540       reftime2=reftime1+1;\r
541       firstsynched=true;\r
542     } else {\r
543       if (!firstsynched) {//\r
544         *samplepos=packet.length;//if we have not processed at least one\r
545         return packet.length;//synched packet ignore it!\r
546       }\r
547     }\r
548   }\r
549   BYTE *ms_buf;\r
550   UINT ms_length;\r
551   UINT ms_pos;\r
552   UINT haveToCopy;\r
553   if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample\r
554     samplepos=0;\r
555     MILLISLEEP(10);\r
556     return 0;\r
557   }\r
558   ms_pos=ms->GetActualDataLength();\r
559   ms_length=ms->GetSize();\r
560   haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);\r
561   if ((ms_length-ms_pos)<1) {\r
562     DeliverVideoMediaSample(); //we are full!\r
563     if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample\r
564       samplepos=0;\r
565       MILLISLEEP(10);\r
566       return 0;\r
567     }\r
568     ms_pos=ms->GetActualDataLength();\r
569     ms_length=ms->GetSize();\r
570     haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);\r
571   }\r
572   ms->GetPointer(&ms_buf);\r
573 \r
574 \r
575   if (ms_pos==0) {//will only be changed on first packet\r
576     if (packet.disconti) {\r
577       ms->SetDiscontinuity(TRUE);\r
578     } else {\r
579       ms->SetDiscontinuity(FALSE);\r
580     }\r
581     if (packet.synched) {\r
582       ms->SetSyncPoint(TRUE);\r
583       ms->SetTime(&reftime1,&reftime2);\r
584       //ms->SetTime(NULL,NULL);\r
585       ms->SetMediaTime(NULL, NULL);\r
586     if (reftime1<0) ms->SetPreroll(TRUE);\r
587     else ms->SetPreroll(FALSE);\r
588     /*Timecode handling*/\r
589     lastreftimeRT=reftime1;\r
590         lastreftimePTS=packet.pts;\r
591 \r
592     }else {\r
593       ms->SetSyncPoint(FALSE);\r
594       ms->SetTime(NULL,NULL);\r
595       ms->SetMediaTime(NULL, NULL);\r
596     ms->SetPreroll(FALSE);\r
597 \r
598     //  ms->SetSyncPoint(TRUE);\r
599     }\r
600   }\r
601 \r
602 \r
603   memcpy(ms_buf+ms_pos,buffer+packet.pos_buffer+*samplepos,haveToCopy);\r
604     ms->SetActualDataLength(haveToCopy+ms_pos);\r
605 \r
606   *samplepos+=haveToCopy;\r
607 \r
608   return haveToCopy+headerstrip;\r
609 \r
610 #else\r
611 \r
612        *samplepos+=packet.length;\r
613       MILLISLEEP(0); //yet not implemented//bad idea\r
614        return packet.length;\r
615 #endif\r
616 }\r
617 \r
618 int VideoWin::getCurrentAudioMediaSample(IMediaSample** ms)\r
619 {\r
620   //WaitForSingleObject(filtermutex,INFINITE);\r
621   if (!sourcefilter){\r
622   //  ReleaseMutex(filtermutex);\r
623     return 0;\r
624   }\r
625   if (cur_audio_media_sample) {\r
626     *ms=cur_audio_media_sample;//already open\r
627     return 1;\r
628   }\r
629   if (!sourcefilter->getCurrentAudioMediaSample(ms)) {\r
630   //  ReleaseMutex(filtermutex);\r
631   }\r
632   if (*ms) (*ms)->SetActualDataLength(0);\r
633   cur_audio_media_sample=*ms;\r
634   //Don't release the mutex before deliver\r
635   return 1;\r
636 }\r
637 \r
638 int VideoWin::getCurrentVideoMediaSample(IMediaSample** ms)\r
639 {\r
640   //WaitForSingleObject(filtermutex,INFINITE);\r
641   if (!sourcefilter){\r
642   //  ReleaseMutex(filtermutex);\r
643     return 0;\r
644   }\r
645   if (cur_video_media_sample) {\r
646     *ms=cur_video_media_sample;//already open\r
647     return 1;\r
648   }\r
649   if (!sourcefilter->getCurrentVideoMediaSample(ms)) {\r
650   //  ReleaseMutex(filtermutex);\r
651   }\r
652   if (*ms) (*ms)->SetActualDataLength(0);\r
653 \r
654   cur_video_media_sample=*ms;\r
655   //Don't release the mutex before deliver\r
656   return 1;\r
657 }\r
658 \r
659 int VideoWin::DeliverAudioMediaSample(){\r
660   if (cur_audio_media_sample) {\r
661     sourcefilter->DeliverAudioMediaSample(cur_audio_media_sample);\r
662     cur_audio_media_sample=NULL;\r
663   }\r
664   //ReleaseMutex(filtermutex);\r
665   return 1;\r
666 }\r
667 \r
668 int VideoWin::DeliverVideoMediaSample(){\r
669   if (cur_video_media_sample) {\r
670     sourcefilter->DeliverVideoMediaSample(cur_video_media_sample);\r
671     cur_video_media_sample=NULL;\r
672   }\r
673   //ReleaseMutex(filtermutex);\r
674   return 1;\r
675 }\r
676 \r
677 long long VideoWin::SetStartOffset(long long curreftime, bool *rsync)\r
678 {\r
679   *rsync=false;\r
680   if (offsetnotset) {\r
681     startoffset=curreftime;//offset is set for audio\r
682     offsetnotset=false;\r
683     offsetvideonotset=false;\r
684 \r
685 \r
686   } else {\r
687     if (offsetvideonotset) {\r
688       offsetvideonotset=false;\r
689       *rsync=true;\r
690     } else {\r
691       if ( (curreftime-lastrefvideotime)>10000000LL\r
692         || (curreftime-lastrefvideotime)<-10000000LL) {//if pts jumps to big resync\r
693         startoffset+=curreftime-lastrefvideotime;\r
694         lastrefaudiotime+=curreftime-lastrefvideotime;\r
695         //*rsync=true;\r
696         offsetaudionotset=true;\r
697 \r
698       }\r
699     }\r
700 \r
701   }\r
702 \r
703   lastrefvideotime=curreftime;\r
704   \r
705   return startoffset;\r
706 \r
707 }\r
708 \r
709 long long VideoWin::SetStartAudioOffset(long long curreftime, bool *rsync)\r
710 {\r
711   *rsync=false;\r
712   if (offsetnotset) {\r
713     startoffset=curreftime;\r
714     offsetnotset=false;\r
715     offsetaudionotset=false;\r
716   }else {\r
717     if (offsetaudionotset) {\r
718       offsetaudionotset=false;\r
719       *rsync=true;\r
720     } else {\r
721       if ( (curreftime-lastrefaudiotime)>10000000LL\r
722         || (curreftime-lastrefaudiotime)<-10000000LL) {//if pts jumps to big resync\r
723         startoffset+=curreftime-lastrefaudiotime;\r
724         lastrefvideotime+=curreftime-lastrefaudiotime;\r
725         //*rsync=true;\r
726         offsetvideonotset=true;\r
727 \r
728       }\r
729     }\r
730 \r
731   }\r
732   lastrefaudiotime=curreftime;\r
733   return startoffset;\r
734 \r
735 }\r
736 void VideoWin::ResetTimeOffsets() {\r
737   offsetnotset=true; //called from demuxer\r
738   offsetvideonotset=true;\r
739   offsetaudionotset=true;\r
740   startoffset=0;\r
741   lastrefaudiotime=0;\r
742   lastrefvideotime=0;\r
743   lastreftimeRT=0;\r
744   lastreftimePTS=0;\r
745 \r
746 \r
747 }\r
748 \r
749 void VideoWin::SetAudioVolume(long volume)\r
750 {\r
751         if (dsbasicaudio) dsbasicaudio->put_Volume(volume);\r
752 }\r
753 \r
754 #ifdef DEV\r
755 int VideoWin::test()\r
756 {\r
757   return 0;\r
758 }\r
759 \r
760 int VideoWin::test2()\r
761 {\r
762   return 0;\r
763 }\r
764 #endif\r
765 \r
766 \r