]> 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   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 //So this is the real code, this prevents the feeder from calling noexisting objects!\r
215    WaitForSingleObject(filtermutex,INFINITE);\r
216   if (hres=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,\r
217     IID_IGraphBuilder,(void**)&dsgraphbuilder)!=S_OK) {\r
218           ReleaseMutex(filtermutex);\r
219       return 0;\r
220    }\r
221    #ifdef DS_DEBUG\r
222    AddToRot(dsgraphbuilder,&graphidentifier);\r
223    #endif\r
224    //This is just a try to see if building the graph works\r
225 //   dsgraphbuilder->RenderFile(L"D:\\Projekte\\VTP Client\\test.mpa" ,NULL);\r
226    \r
227    firstsynched=false;\r
228    sourcefilter=new DsSourceFilter(); //Creating our Source filter for pushing Data\r
229    // to DirectShow\r
230    sourcefilter->AddRef();\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 \r
317    hresdeb=dsmediacontrol->Run();\r
318    iframemode=false;//exit iframe mode\r
319    ReleaseMutex(filtermutex);\r
320   return 1;\r
321 }\r
322 \r
323 int VideoWin::EnterIframePlayback()\r
324 {\r
325         if (!initted) return 0;\r
326         CleanupDS();\r
327         //So this is the real code, this prevents the feeder from calling noexisting objects!\r
328    WaitForSingleObject(filtermutex,INFINITE);\r
329         iframemode=true;//enter iframe mode\r
330         //Build filter graph\r
331         HRESULT hres;\r
332         if (hres=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,\r
333                  IID_IGraphBuilder,(void**)&dsgraphbuilder)!=S_OK) {\r
334                          ReleaseMutex(filtermutex);\r
335                          return 0;\r
336         }\r
337 #ifdef DS_DEBUG\r
338         AddToRot(dsgraphbuilder,&graphidentifier);\r
339 #endif\r
340    \r
341    //firstsynched=false;\r
342    sourcefilter=new DsSourceFilter(); //Creating our Source filter for pushing Data\r
343    // to DirectShow\r
344    sourcefilter->AddRef();\r
345    if (hres=dsgraphbuilder->AddFilter(sourcefilter,L"Vomp Win Source Filter")!=S_OK) {\r
346    Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Vomp Source Filter!");\r
347      ReleaseMutex(filtermutex);  \r
348      CleanupDS();\r
349      return 0;\r
350    }\r
351 #ifdef DO_VIDEO\r
352     if (videoon) {\r
353     //We alloc the vmr9 as next step\r
354     if (hres=CoCreateInstance(CLSID_VideoMixingRenderer9,0,\r
355       CLSCTX_INPROC_SERVER,IID_IBaseFilter,(void**) &dsvmrrenderer)!=S_OK) {\r
356       Log::getInstance()->log("VideoWin", Log::WARN ,"Failed creating VMR9 renderer!");\r
357       ReleaseMutex(filtermutex);\r
358           CleanupDS();\r
359           return 0;\r
360     }\r
361       /*VMR 9 stuff**/\r
362     if (hres=dsgraphbuilder->AddFilter(dsvmrrenderer,L"VMR9")!=S_OK) {\r
363       Log::getInstance()->log("VideoWin", Log::WARN ,"Failed adding VMR9 renderer!");\r
364       ReleaseMutex(filtermutex);\r
365           CleanupDS();\r
366       return 0;\r
367     }\r
368     IVMRFilterConfig9* vmrfilconfig;\r
369     if (dsvmrrenderer->QueryInterface(IID_IVMRFilterConfig9,(void**)&vmrfilconfig)!=S_OK) {\r
370       ReleaseMutex(filtermutex);\r
371           CleanupDS();\r
372       Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Filterconfig interface!");\r
373       \r
374       return 0;\r
375     }\r
376     vmrfilconfig->SetRenderingMode(VMR9Mode_Renderless);\r
377     vmrfilconfig->Release();\r
378 \r
379     if (dsvmrrenderer->QueryInterface(IID_IVMRSurfaceAllocatorNotify9,(void**)& dsvmrsurfnotify)!=S_OK) { \r
380       Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Surface Allocator interface!");\r
381       ReleaseMutex(filtermutex);\r
382           CleanupDS();\r
383       return 0;\r
384     }\r
385     allocatorvmr=new DsAllocator();\r
386     dsvmrsurfnotify->AdviseSurfaceAllocator(NULL,allocatorvmr);\r
387     allocatorvmr->AdviseNotify(dsvmrsurfnotify);\r
388         \r
389     /*VMR 9 stuff end */\r
390     IFilterGraph2*fg2=NULL;\r
391     if (dsgraphbuilder->QueryInterface(IID_IFilterGraph2,(void**)&fg2)!=S_OK) {\r
392       Log::getInstance()->log("VideoWin", Log::WARN , "Failed querying for FilterGraph2 Interface!");\r
393       ReleaseMutex(filtermutex);\r
394           CleanupDS();\r
395       return 0;\r
396     }\r
397     if (hres=fg2->RenderEx((IPin*)sourcefilter->GetVideoPin()/*video*/,\r
398         AM_RENDEREX_RENDERTOEXISTINGRENDERERS,NULL)!=S_OK) {\r
399       Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering Video!");\r
400           fg2->Release();\r
401           ReleaseMutex(filtermutex);\r
402       CleanupDS();\r
403       return 0;\r
404     }\r
405         fg2->Release();\r
406    }\r
407 #endif\r
408 /*   if (hres=CoCreateInstance(CLSID_SystemClock,NULL,CLSCTX_INPROC_SERVER,\r
409     IID_IReferenceClock,(void**)&dsrefclock)!=S_OK) {\r
410       return 0;\r
411    }*/\r
412 \r
413    dsgraphbuilder->QueryInterface(IID_IMediaFilter,(void **) &dsmediafilter);\r
414    dsmediafilter->SetSyncSource(/*dsrefclock*/NULL); //Run as fast as you can!\r
415 \r
416    dsgraphbuilder->QueryInterface(IID_IMediaControl,(void **) &dsmediacontrol);\r
417    dsgraphbuilder->QueryInterface(IID_IBasicAudio,(void **) &dsbasicaudio);     \r
418 \r
419    dsmediacontrol->Run();\r
420    ReleaseMutex(filtermutex);\r
421   return 1;\r
422 \r
423 }\r
424 \r
425 int VideoWin::dsstop()\r
426 {\r
427   if (!initted) return 0;\r
428 \r
429   CleanupDS();\r
430 \r
431 \r
432   return 1;\r
433 }\r
434 \r
435 int VideoWin::stop()\r
436 {\r
437   if (!initted) return 0;\r
438 \r
439 \r
440   return 1;\r
441 }\r
442 \r
443 int VideoWin::reset()\r
444 {\r
445   if (!initted) return 0;\r
446   \r
447 \r
448   return 1;\r
449 }\r
450 \r
451 int VideoWin::dsreset()\r
452 {\r
453   if (!initted) return 0;\r
454   videoposx=0;\r
455   videoposy=0;\r
456   iframemode=false;//exit iframe mode\r
457   CleanupDS();\r
458 \r
459   return 1;\r
460 }\r
461 \r
462 int VideoWin::dspause()\r
463 {\r
464   if (!initted) return 0;\r
465   WaitForSingleObject(filtermutex,INFINITE);\r
466   if (dsmediacontrol) dsmediacontrol->Pause();\r
467   ReleaseMutex(filtermutex);\r
468   return 1;\r
469 }\r
470 \r
471 int VideoWin::pause()\r
472 {\r
473   if (!initted) return 0;\r
474   \r
475   return 1;\r
476 }\r
477 \r
478 int VideoWin::unPause() // FIXME get rid - same as play!!\r
479 {//No on windows this is not the same, I don't get rid of!\r
480   if (!initted) return 0;\r
481   return 1;\r
482 }\r
483 \r
484 int VideoWin::dsunPause() // FIXME get rid - same as play!!\r
485 {//No on windows this is not the same, I don't get rid of!\r
486   if (!initted) return 0;\r
487   WaitForSingleObject(filtermutex,INFINITE);\r
488   if (dsmediacontrol) dsmediacontrol->Run();\r
489   ReleaseMutex(filtermutex);\r
490 \r
491   return 1;\r
492 }\r
493 \r
494 int VideoWin::fastForward()\r
495 {\r
496   if (!initted) return 0;\r
497 \r
498   return 1;\r
499 }\r
500 \r
501 int VideoWin::unFastForward()\r
502 {\r
503   if (!initted) return 0;\r
504   \r
505   return 1;\r
506 }\r
507 \r
508 int VideoWin::attachFrameBuffer()\r
509 {\r
510   if (!initted) return 0;\r
511   return 1;\r
512 }\r
513 \r
514 int VideoWin::blank(void)\r
515 {\r
516   ((OsdWin*)Osd::getInstance())->Blank();\r
517   return 1;\r
518 }\r
519 \r
520 ULLONG VideoWin::getCurrentTimestamp()\r
521 {\r
522         REFERENCE_TIME startoffset;\r
523         REFERENCE_TIME ncr_time;\r
524   if (iframemode) return 0; //Not in iframe mode!\r
525   if (!dsrefclock || !sourcefilter) return 0;\r
526         FILTER_STATE state;\r
527         sourcefilter->GetState(10,&state);\r
528 \r
529         if (state==State_Running) dsrefclock->GetTime(&cr_time);\r
530         ncr_time=cr_time;\r
531   startoffset=sourcefilter->getStartOffset();\r
532         ncr_time-=startoffset;\r
533         ncr_time-=lastreftimeRT;\r
534  /* ULLONG result=frameNumberToTimecode(\r
535     VDR::getInstance()->frameNumberFromPosition(lastreftimeBYTE));*/\r
536         ULLONG result=lastreftimePTS;\r
537         result+=(ULLONG)(ncr_time/10000LL*90LL);\r
538   return result;\r
539 \r
540 }\r
541 \r
542 ULONG VideoWin::timecodeToFrameNumber(ULLONG timecode)\r
543 {\r
544   if (format == PAL) return (ULONG)(((double)timecode / (double)90000) * (double)25);\r
545   else               return (ULONG)(((double)timecode / (double)90000) * (double)30);\r
546 }\r
547 \r
548 ULLONG VideoWin::frameNumberToTimecode(ULONG framenumber)\r
549 {\r
550   if (format == PAL) return (ULLONG)(((double)framenumber * (double)90000) / (double)25);\r
551   else               return (ULLONG)(((double)framenumber * (double)90000) / (double)30);\r
552 }\r
553 \r
554 void VideoWin::CleanupDS()\r
555 {\r
556   WaitForSingleObject(filtermutex,INFINITE);\r
557   if (dsmediacontrol)dsmediacontrol->Stop();\r
558   if (cur_audio_media_sample) {\r
559     cur_audio_media_sample->Release();\r
560     cur_audio_media_sample=NULL;\r
561   }\r
562   if (cur_video_media_sample) {\r
563     cur_video_media_sample->Release();\r
564     cur_video_media_sample=NULL;\r
565   }\r
566   if (dsbasicaudio) {\r
567           dsbasicaudio->Release();\r
568           dsbasicaudio=NULL;\r
569   }\r
570   if (dsvmrsurfnotify) {\r
571     dsvmrsurfnotify->Release();\r
572     dsvmrsurfnotify=NULL;\r
573   }\r
574   if (dsvmrrenderer) {\r
575     dsvmrrenderer->Release();\r
576     dsvmrrenderer=NULL;\r
577   }\r
578 \r
579   if (allocatorvmr) {\r
580     allocatorvmr->Release();\r
581     allocatorvmr=NULL;\r
582   }\r
583 \r
584   if (dsrefclock) {\r
585     dsrefclock->Release();\r
586     dsrefclock=NULL;\r
587   }\r
588   if (dsmediafilter) {\r
589     dsmediafilter->Release();\r
590     dsmediafilter=NULL;\r
591   }\r
592 \r
593 \r
594 \r
595   if (dsmediacontrol) {\r
596     dsmediacontrol->Stop();\r
597     dsmediacontrol->Release();\r
598     dsmediacontrol=NULL;\r
599   }\r
600   if (dsgraphbuilder){\r
601 #ifdef DS_DEBUG\r
602     RemoveFromRot(graphidentifier);\r
603 #endif\r
604     dsgraphbuilder->Release();\r
605     dsgraphbuilder=NULL;\r
606         sourcefilter->Release();\r
607     sourcefilter=NULL; //The Graph Builder destroys our SourceFilter\r
608   }\r
609   ReleaseMutex(filtermutex);\r
610 \r
611 }\r
612 \r
613 void VideoWin::PrepareMediaSample(const MediaPacketList& mplist,\r
614      UINT samplepos)\r
615 {\r
616   mediapacket = mplist.front();\r
617 }\r
618 \r
619 UINT VideoWin::DeliverMediaSample(const UCHAR* buffer, UINT *samplepos)\r
620 {\r
621   DeliverMediaPacket(mediapacket, buffer, samplepos);\r
622   if (*samplepos == mediapacket.length) {\r
623     *samplepos = 0;\r
624     return 1;\r
625   }\r
626   else return 0;\r
627 }\r
628 \r
629 UINT VideoWin::DeliverMediaPacket(MediaPacket packet,\r
630      const UCHAR* buffer,\r
631      UINT *samplepos)\r
632 {\r
633   /*First Check, if we have an audio sample*/\r
634 #ifdef DO_VIDEO\r
635         if (!videoon) {\r
636           *samplepos+=packet.length;\r
637        MILLISLEEP(0); //yet not implemented//bad idea\r
638        return packet.length;\r
639         }\r
640   /*First Check, if we have an audio sample*/\r
641   if (iframemode) {\r
642                 samplepos=0;\r
643                 MILLISLEEP(10);\r
644                 return 0; //Not in iframe mode!\r
645   }\r
646   IMediaSample* ms=NULL;\r
647   REFERENCE_TIME reftime1=0;\r
648   REFERENCE_TIME reftime2=0;\r
649 \r
650   UINT headerstrip=0;\r
651   if (packet.disconti) {\r
652     firstsynched=false;\r
653     DeliverVideoMediaSample();\r
654 \r
655   }\r
656 \r
657 \r
658   /*Inspect PES-Header */\r
659 \r
660   if (*samplepos==0) {//stripheader\r
661     headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/;\r
662     *samplepos+=headerstrip;\r
663     if ( packet.synched ) {\r
664       DeliverVideoMediaSample();//write out old data\r
665    /*   if (packet.presentation_time<0) { //Preroll?\r
666         *samplepos=packet.length;//if we have not processed at least one\r
667         return packet.length;//synched packet ignore it!\r
668       }*/\r
669 \r
670       reftime1=packet.presentation_time;\r
671       reftime2=reftime1+1;\r
672       firstsynched=true;\r
673     } else {\r
674       if (!firstsynched) {//\r
675         *samplepos=packet.length;//if we have not processed at least one\r
676         return packet.length;//synched packet ignore it!\r
677       }\r
678     }\r
679   }\r
680   BYTE *ms_buf;\r
681   UINT ms_length;\r
682   UINT ms_pos;\r
683   UINT haveToCopy;\r
684   \r
685   if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample\r
686     samplepos=0;\r
687     MILLISLEEP(10);\r
688     return 0;\r
689   }\r
690   ms_pos=ms->GetActualDataLength();\r
691   ms_length=ms->GetSize();\r
692   haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);\r
693   if ((ms_length-ms_pos)<1) {\r
694     DeliverVideoMediaSample(); //we are full!\r
695     if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample\r
696       samplepos=0;\r
697       MILLISLEEP(10);\r
698       return 0;\r
699     }\r
700     ms_pos=ms->GetActualDataLength();\r
701     ms_length=ms->GetSize();\r
702     haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);\r
703   }\r
704   ms->GetPointer(&ms_buf);\r
705 \r
706 \r
707   if (ms_pos==0) {//will only be changed on first packet\r
708     if (packet.disconti) {\r
709       ms->SetDiscontinuity(TRUE);\r
710     } else {\r
711       ms->SetDiscontinuity(FALSE);\r
712     }\r
713     if (packet.synched) {\r
714       ms->SetSyncPoint(TRUE);\r
715       ms->SetTime(&reftime1,&reftime2);\r
716       //ms->SetTime(NULL,NULL);\r
717       ms->SetMediaTime(NULL, NULL);\r
718     if (reftime1<0) ms->SetPreroll(TRUE);\r
719     else ms->SetPreroll(FALSE);\r
720     /*Timecode handling*/\r
721     lastreftimeRT=reftime1;\r
722         lastreftimePTS=packet.pts;\r
723 \r
724     }else {\r
725       ms->SetSyncPoint(FALSE);\r
726       ms->SetTime(NULL,NULL);\r
727       ms->SetMediaTime(NULL, NULL);\r
728     ms->SetPreroll(FALSE);\r
729 \r
730     //  ms->SetSyncPoint(TRUE);\r
731     }\r
732   }\r
733 \r
734 \r
735   memcpy(ms_buf+ms_pos,buffer+packet.pos_buffer+*samplepos,haveToCopy);\r
736     ms->SetActualDataLength(haveToCopy+ms_pos);\r
737 \r
738   *samplepos+=haveToCopy;\r
739 \r
740   return haveToCopy+headerstrip;\r
741 \r
742 #else\r
743 \r
744        *samplepos+=packet.length;\r
745       MILLISLEEP(0); //yet not implemented//bad idea\r
746        return packet.length;\r
747 #endif\r
748 }\r
749 \r
750 int VideoWin::getCurrentAudioMediaSample(IMediaSample** ms)\r
751 {\r
752   //WaitForSingleObject(filtermutex,INFINITE);\r
753   if (!sourcefilter){\r
754   //  ReleaseMutex(filtermutex);\r
755     return 0;\r
756   }\r
757   if (cur_audio_media_sample) {\r
758     *ms=cur_audio_media_sample;//already open\r
759     return 1;\r
760   }\r
761   if (!sourcefilter->getCurrentAudioMediaSample(ms)) {\r
762   //  ReleaseMutex(filtermutex);\r
763   }\r
764   if (*ms) (*ms)->SetActualDataLength(0);\r
765   cur_audio_media_sample=*ms;\r
766   //Don't release the mutex before deliver\r
767   return 1;\r
768 }\r
769 \r
770 int VideoWin::getCurrentVideoMediaSample(IMediaSample** ms)\r
771 {\r
772   //WaitForSingleObject(filtermutex,INFINITE);\r
773   if (!sourcefilter){\r
774   //  ReleaseMutex(filtermutex);\r
775     return 0;\r
776   }\r
777   if (cur_video_media_sample) {\r
778     *ms=cur_video_media_sample;//already open\r
779     return 1;\r
780   }\r
781   if (!sourcefilter->getCurrentVideoMediaSample(ms)) {\r
782   //  ReleaseMutex(filtermutex);\r
783   }\r
784   if (*ms) (*ms)->SetActualDataLength(0);\r
785 \r
786   cur_video_media_sample=*ms;\r
787   //Don't release the mutex before deliver\r
788   return 1;\r
789 }\r
790 \r
791 int VideoWin::DeliverAudioMediaSample(){\r
792   if (cur_audio_media_sample) {\r
793     sourcefilter->DeliverAudioMediaSample(cur_audio_media_sample);\r
794     cur_audio_media_sample=NULL;\r
795   }\r
796   //ReleaseMutex(filtermutex);\r
797   return 1;\r
798 }\r
799 \r
800 int VideoWin::DeliverVideoMediaSample(){\r
801   if (cur_video_media_sample) {\r
802     sourcefilter->DeliverVideoMediaSample(cur_video_media_sample);\r
803     cur_video_media_sample=NULL;\r
804   }\r
805   //ReleaseMutex(filtermutex);\r
806   return 1;\r
807 }\r
808 \r
809 long long VideoWin::SetStartOffset(long long curreftime, bool *rsync)\r
810 {\r
811   *rsync=false;\r
812   if (offsetnotset) {\r
813     startoffset=curreftime;//offset is set for audio\r
814     offsetnotset=false;\r
815     offsetvideonotset=false;\r
816 \r
817 \r
818   } else {\r
819     if (offsetvideonotset) {\r
820       offsetvideonotset=false;\r
821       *rsync=true;\r
822     } else {\r
823       if ( (curreftime-lastrefvideotime)>10000000LL\r
824         || (curreftime-lastrefvideotime)<-10000000LL) {//if pts jumps to big resync\r
825         startoffset+=curreftime-lastrefvideotime;\r
826         lastrefaudiotime+=curreftime-lastrefvideotime;\r
827         //*rsync=true;\r
828         offsetaudionotset=true;\r
829 \r
830       }\r
831     }\r
832 \r
833   }\r
834 \r
835   lastrefvideotime=curreftime;\r
836   \r
837   return startoffset;\r
838 \r
839 }\r
840 \r
841 long long VideoWin::SetStartAudioOffset(long long curreftime, bool *rsync)\r
842 {\r
843   *rsync=false;\r
844   if (offsetnotset) {\r
845     startoffset=curreftime;\r
846     offsetnotset=false;\r
847     offsetaudionotset=false;\r
848   }else {\r
849     if (offsetaudionotset) {\r
850       offsetaudionotset=false;\r
851       *rsync=true;\r
852     } else {\r
853       if ( (curreftime-lastrefaudiotime)>10000000LL\r
854         || (curreftime-lastrefaudiotime)<-10000000LL) {//if pts jumps to big resync\r
855         startoffset+=curreftime-lastrefaudiotime;\r
856         lastrefvideotime+=curreftime-lastrefaudiotime;\r
857         //*rsync=true;\r
858         offsetvideonotset=true;\r
859 \r
860       }\r
861     }\r
862 \r
863   }\r
864   lastrefaudiotime=curreftime;\r
865   return startoffset;\r
866 \r
867 }\r
868 void VideoWin::ResetTimeOffsets() {\r
869   offsetnotset=true; //called from demuxer\r
870   offsetvideonotset=true;\r
871   offsetaudionotset=true;\r
872   startoffset=0;\r
873   lastrefaudiotime=0;\r
874   lastrefvideotime=0;\r
875   lastreftimeRT=0;\r
876   lastreftimePTS=0;\r
877 \r
878 \r
879 }\r
880 \r
881 void VideoWin::SetAudioVolume(long volume)\r
882 {\r
883         if (dsbasicaudio) dsbasicaudio->put_Volume(volume);\r
884 }\r
885 \r
886 void VideoWin::displayIFrame(const UCHAR* buffer, UINT length)\r
887 {\r
888         if (!iframemode) EnterIframePlayback();\r
889 \r
890 \r
891 #ifdef DO_VIDEO\r
892   IMediaSample* ms=NULL;\r
893   REFERENCE_TIME reftime1=0;\r
894   REFERENCE_TIME reftime2=0;\r
895   if (!videoon) return;\r
896 \r
897   if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample\r
898     MILLISLEEP(10);\r
899     return ;\r
900   }\r
901   BYTE *ms_buf;\r
902   DWORD ms_length;\r
903   ms->GetPointer(&ms_buf);\r
904   ms_length=ms->GetSize();\r
905   \r
906   /*First Check, if we have an video sample*/\r
907   DWORD read_pos = 0, write_pos = 0;\r
908   DWORD pattern, packet_length;\r
909   DWORD headerstrip=0;\r
910   bool first=true;\r
911   if (length < 4) return ;\r
912   //Now we strip the pes header\r
913   pattern = (buffer[0] << 16) | (buffer[1] << 8) | (buffer[2]);\r
914   while (read_pos + 7 <= length)\r
915   {\r
916     pattern = ((pattern << 8) & 0xFFFFFFFF) | buffer[read_pos+3];\r
917     if (pattern < 0x000001E0 || pattern > 0x000001EF)\r
918       read_pos++;\r
919     else\r
920     {\r
921           headerstrip=buffer[read_pos+8]+9/*is this right*/;\r
922       packet_length = ((buffer[read_pos+4] << 8) | (buffer[read_pos+5])) + 6;\r
923       if (read_pos + packet_length > length)\r
924         read_pos = length;\r
925       else\r
926       {\r
927                   if ((write_pos+packet_length-headerstrip)>ms_length) {\r
928                           if (first) {ms->SetSyncPoint(TRUE);first=false;} \r
929                           else ms->SetSyncPoint(FALSE);\r
930                           ms->SetTime(NULL,NULL);\r
931                           ms->SetMediaTime(NULL, NULL);\r
932                           ms->SetActualDataLength(write_pos);\r
933                           DeliverVideoMediaSample();\r
934 \r
935                           if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample\r
936                                 MILLISLEEP(10);\r
937                                 return ;\r
938                           }\r
939                           write_pos=0;\r
940                           ms_length=ms->GetSize();\r
941                           ms->GetPointer(&ms_buf);\r
942                   }\r
943                   if (packet_length-headerstrip>0) {\r
944                         memcpy(ms_buf+write_pos, buffer+read_pos+headerstrip, packet_length-headerstrip);\r
945                         write_pos += packet_length-headerstrip;\r
946                   }\r
947                   read_pos += packet_length;\r
948                   \r
949                   pattern = (buffer[read_pos] << 16) | (buffer[read_pos+1] << 8)\r
950                                         | (buffer[read_pos+2]);\r
951       }\r
952     }\r
953   }\r
954 \r
955   if (first) {ms->SetSyncPoint(TRUE);first=false;} \r
956   else ms->SetSyncPoint(FALSE);\r
957   ms->SetTime(NULL,NULL);\r
958   ms->SetMediaTime(NULL, NULL);\r
959   ms->SetActualDataLength(write_pos);\r
960   DeliverVideoMediaSample();\r
961 \r
962 #else\r
963 \r
964     //   *samplepos+=packet.length;\r
965       MILLISLEEP(0); //yet not implemented//bad idea\r
966        return ;\r
967 #endif\r
968 }\r
969 \r
970 \r
971 #ifdef DEV\r
972 int VideoWin::test()\r
973 {\r
974   return 0;\r
975 }\r
976 \r
977 int VideoWin::test2()\r
978 {\r
979   return 0;\r
980 }\r
981 #endif\r
982 \r
983 \r