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