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