]> git.vomp.tv Git - vompclient-marten.git/blob - dsallocator.cc
Fix bug in demuxer widescreen signaling
[vompclient-marten.git] / dsallocator.cc
1 /*
2     Copyright 2004-2005 Chris Tallon, Marten Richter
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 */
20
21 #define INITGUID
22
23 #include "osdwin.h"
24 #include "dsallocator.h"
25
26 #include <math.h>
27
28 #include <mfidl.h>
29 #include <Mfapi.h>
30 #include <mferror.h>
31
32 typedef HRESULT (__stdcall *FCT_MFCreateVideoSampleFromSurface)(IUnknown* pUnkSurface, IMFSample** ppSample);
33
34 extern FCT_MFCreateVideoSampleFromSurface ptrMFCreateVideoSampleFromSurface;
35
36
37 DsAllocator::DsAllocator() {
38     surfallocnotify=NULL;
39     refcount=1;
40     inevrmode=false;
41     mftransform=NULL;
42     mediasink=NULL;
43     mfclock=NULL;
44     mfmediatype=NULL;
45     endofstream=false;
46     start_get_evr_samples=false;
47     ResetSyncOffsets();
48
49
50
51 }
52
53 DsAllocator::~DsAllocator() {
54     ((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_off);
55     ((OsdWin*)Osd::getInstance())->setExternalDriving(NULL,vwidth,vheight);
56     CleanupSurfaces();
57
58 }
59
60 void DsAllocator::CleanupSurfaces() {
61     Lock();
62     while(fullevrsamples.size()>0)
63     {
64         IMFSample *sample=fullevrsamples.front();
65         fullevrsamples.pop();
66         sample->Release();
67     }
68     while(emptyevrsamples.size()>0)
69     {
70         IMFSample *sample=emptyevrsamples.front();
71         emptyevrsamples.pop();
72         sample->Release();
73     }
74
75     for (int i=0;i<surfaces.size();i++) {
76         if (surfaces[i]!=NULL) surfaces[i]->Release();
77         surfaces[i]=NULL;
78     }
79     start_get_evr_samples=false;
80     Unlock();
81 }
82
83 HRESULT STDMETHODCALLTYPE DsAllocator::InitializeDevice(DWORD_PTR userid,VMR9AllocationInfo* allocinf,DWORD*numbuf){
84     if (!surfallocnotify) return S_FALSE;
85
86     CleanupSurfaces();
87     Lock();
88     surfaces.resize(*numbuf);
89     HRESULT hres= surfallocnotify->AllocateSurfaceHelper(allocinf,numbuf,&surfaces.at(0));
90     vheight=allocinf->dwHeight;
91     vwidth=allocinf->dwWidth;
92     start_get_evr_samples=false;
93     Unlock();
94     /*  char buffer[1024];
95     sprintf(buffer,"%d * %d",allocinf->dwWidth,allocinf->dwHeight);
96     MessageBox(0,"hi",buffer,0);*/
97     return hres;
98 }
99
100 void DsAllocator::LostDevice(IDirect3DDevice9 *d3ddev, IDirect3D9* d3d) {
101     if (!surfallocnotify) return ;
102     CleanupSurfaces();
103     Lock();
104     //  d3ddev=((OsdWin*)Osd::getInstance())->getD3dDev();
105     HMONITOR hmon=d3d->GetAdapterMonitor(D3DADAPTER_DEFAULT);
106     surfallocnotify->ChangeD3DDevice(d3ddev,hmon);
107     Unlock();
108
109 }
110
111 HRESULT STDMETHODCALLTYPE DsAllocator::TerminateDevice(DWORD_PTR userid){
112     CleanupSurfaces();
113
114     return S_OK; //Do nothing
115 }
116 HRESULT STDMETHODCALLTYPE DsAllocator::GetSurface(DWORD_PTR userid,DWORD surfindex,DWORD surfflags, IDirect3DSurface9** surf)
117 {
118     if (surfindex>=surfaces.size()) return E_FAIL;
119     if (surf==NULL) return E_POINTER;
120
121     Lock();
122     surfaces[surfindex]->AddRef();
123     *surf=surfaces[surfindex];
124     Unlock();
125     return S_OK;
126 }
127 HRESULT STDMETHODCALLTYPE DsAllocator::AdviseNotify(IVMRSurfaceAllocatorNotify9* allnoty){
128     Lock();
129     surfallocnotify=allnoty;
130     IDirect3DDevice9 *d3ddev;
131     //OK lets set the direct3d object from the osd
132     d3ddev=((OsdWin*)Osd::getInstance())->getD3dDev();
133     HMONITOR hmon=((OsdWin*)Osd::getInstance())->getD3d()->GetAdapterMonitor(D3DADAPTER_DEFAULT);
134     HRESULT hres=surfallocnotify->SetD3DDevice(d3ddev,hmon);
135     Unlock();
136     return hres;
137 }
138
139
140 HRESULT STDMETHODCALLTYPE DsAllocator::StartPresenting(DWORD_PTR userid){
141     //MessageBox(0,"drive me","drive me",0);
142     ((OsdWin*)Osd::getInstance())->setExternalDriving(this,vwidth,vheight);
143     start_get_evr_samples=false;
144     return S_OK;
145 }
146
147 HRESULT STDMETHODCALLTYPE DsAllocator::StopPresenting(DWORD_PTR userid){
148     ((OsdWin*)Osd::getInstance())->setExternalDriving(NULL,0,0);
149     start_get_evr_samples=false;
150     return S_OK;
151 }
152
153 HRESULT STDMETHODCALLTYPE DsAllocator::PresentImage(DWORD_PTR userid,VMR9PresentationInfo* presinf){
154     ((OsdWin*)Osd::getInstance())->RenderDS(presinf->lpSurf); //render and return
155     return S_OK;
156
157 }
158
159 HRESULT STDMETHODCALLTYPE DsAllocator::QueryInterface(REFIID refiid,void ** obj){
160     if (obj==NULL) return E_POINTER;
161
162     if (refiid==IID_IVMRSurfaceAllocator9) {
163         *obj=static_cast<IVMRSurfaceAllocator9*>(this);
164         AddRef();
165         return S_OK;
166     } else if (refiid==IID_IVMRImagePresenter9) {
167         *obj=static_cast<IVMRImagePresenter9*>(this);
168         AddRef();
169         return S_OK;
170     } else if (refiid==IID_IMFVideoDeviceID) {
171         *obj=static_cast<IMFVideoDeviceID*> (this);
172         AddRef();
173         return S_OK;
174     } else if (refiid==IID_IMFTopologyServiceLookupClient ) {
175         *obj=static_cast<IMFTopologyServiceLookupClient*> (this);
176         AddRef();
177         return S_OK;
178     } else if (refiid==IID_IQualProp ) {
179         *obj=static_cast<IQualProp*> (this);
180         AddRef();
181         return S_OK;
182     }  else if (refiid==IID_IMFGetService) {
183         *obj=static_cast<IMFGetService*> (this);
184         AddRef();
185         return S_OK;
186     } else if (refiid==IID_IDirect3DDeviceManager9) {
187         IDirect3DDeviceManager9 *d3dman=((OsdWin*)Osd::getInstance())->getD3dMan();
188         if (d3dman){
189             return d3dman->QueryInterface(refiid,obj);
190         }
191         else
192         {
193             return E_NOINTERFACE;
194         }
195     }
196     return E_NOINTERFACE;
197 }
198
199
200
201 ULONG STDMETHODCALLTYPE  DsAllocator::AddRef(){
202     return InterlockedIncrement(&refcount);
203 }
204
205 ULONG STDMETHODCALLTYPE DsAllocator::Release(){
206     ULONG ref=0;
207     ref=InterlockedDecrement(&refcount);
208     if (ref==NULL) {
209         delete this; //Commit suicide
210     }
211     return ref;
212 }
213
214 HRESULT STDMETHODCALLTYPE  DsAllocator::GetDeviceID(IID *pDid)
215 {
216     if (pDid==NULL)
217         return E_POINTER;
218
219     *pDid=__uuidof(IDirect3DDevice9);
220     return S_OK;
221 }
222
223 HRESULT STDMETHODCALLTYPE DsAllocator::InitServicePointers(IMFTopologyServiceLookup *plooky)
224 {
225     if (!plooky) return E_POINTER;
226     Lock();
227     inevrmode=true;
228     /* get all interfaces we need*/
229
230     DWORD dwobjcts=1;
231     plooky->LookupService(MF_SERVICE_LOOKUP_GLOBAL,0,MR_VIDEO_MIXER_SERVICE,
232         __uuidof(IMFTransform),(void**)&mftransform, &dwobjcts);
233     plooky->LookupService(MF_SERVICE_LOOKUP_GLOBAL,0,MR_VIDEO_RENDER_SERVICE,
234         __uuidof(IMediaEventSink),(void**)&mediasink, &dwobjcts);
235     plooky->LookupService(MF_SERVICE_LOOKUP_GLOBAL, 0, MR_VIDEO_RENDER_SERVICE,
236         __uuidof(IMFClock),(void**)&mfclock,&dwobjcts);
237
238
239     Unlock();
240     return S_OK;
241 }
242
243 HRESULT STDMETHODCALLTYPE DsAllocator::ReleaseServicePointers()
244 {
245     Lock();
246     inevrmode=false;
247     /* TODO Set RenderState , sample type etc.*/
248
249     ((OsdWin*)Osd::getInstance())->setExternalDriving(NULL,0,0);
250
251     if (mftransform) mftransform->Release();
252     mftransform=NULL;
253
254     if (mediasink) mediasink->Release();
255     mediasink=NULL;
256
257     if (mfclock) mfclock->Release();
258     mfclock=NULL;
259     if (mfmediatype) mfmediatype->Release();
260     mfmediatype=NULL;
261
262     Unlock();
263     return S_OK;
264 }
265
266 HRESULT STDMETHODCALLTYPE DsAllocator::GetService(const GUID &guid,const IID &iid,LPVOID *obj)
267 {
268     if (guid==MR_VIDEO_ACCELERATION_SERVICE)
269     {
270         IDirect3DDeviceManager9 *d3dman=((OsdWin*)Osd::getInstance())->getD3dMan();
271         if (d3dman)
272         {
273             return d3dman->QueryInterface (__uuidof(IDirect3DDeviceManager9), (void**) obj);
274         }
275         else
276         {
277             return E_NOINTERFACE;
278         }
279
280     } 
281     else if (guid==MR_VIDEO_RENDER_SERVICE)
282     {
283         return QueryInterface(iid,obj);
284     } 
285     else
286     {
287         return E_NOINTERFACE;
288     }
289 }
290
291
292 void DsAllocator::GetEVRSamples()
293 {
294     Lock();
295     MFCLOCK_STATE clockstate;
296     if (mfclock) mfclock->GetState(0,&clockstate);
297     //MessageBox(0,"get samples","samples",0);
298     
299     if (mfclock && clockstate==MFCLOCK_STATE_STOPPED && fullevrsamples.size()>0)
300     {
301         Unlock();
302         return;
303     }
304
305     while (emptyevrsamples.size()>0)
306     {
307
308         MFT_OUTPUT_DATA_BUFFER outdatabuffer;
309         ZeroMemory(&outdatabuffer,sizeof(outdatabuffer));
310         outdatabuffer.pSample=emptyevrsamples.front();
311         DWORD status=0;
312         LONGLONG starttime,endtime;
313         MFTIME dummy;
314         starttime=0;
315         endtime=0;
316
317         if (mfclock) 
318         {
319             mfclock->GetCorrelatedTime(0,&starttime,&dummy);
320             if (lastdelframe) CalcJitter( (starttime-lastdelframe)/10000);
321             lastdelframe=starttime;
322         }
323
324         HRESULT hres=mftransform->ProcessOutput(0,1,&outdatabuffer,&status);
325         
326
327         if (hres==MF_E_TRANSFORM_NEED_MORE_INPUT)
328         {
329             if (endofstream)
330             {
331
332                 endofstream=false;
333                 mediasink->Notify(EC_COMPLETE,(LONG_PTR) S_OK,0);
334
335             }
336             break;
337         }
338         else if (hres==MF_E_TRANSFORM_STREAM_CHANGE)
339         {
340             if (mfmediatype) mfmediatype->Release();
341             mfmediatype=NULL;
342             break;
343         } 
344         else if (hres==MF_E_TRANSFORM_TYPE_NOT_SET)
345         {
346             if (mfmediatype) mfmediatype->Release();
347             mfmediatype=NULL;
348             RenegotiateEVRMediaType();
349             break;
350         } 
351         else if (hres==S_OK)
352         {
353             LONGLONG prestime=0;
354             hres=outdatabuffer.pSample->GetSampleTime(&prestime);
355             //Log::getInstance()->log("DsAllocator", Log::DEBUG , "Got EVR Sample %lld",prestime);
356             IMFSample *temp=emptyevrsamples.front();
357             emptyevrsamples.pop();
358
359
360
361             fullevrsamples.push(temp);
362             //Log::getInstance()->log("DsAllocator", Log::DEBUG , "got evr sample %d, %d",
363             //  emptyevrsamples.size(),fullevrsamples.size());
364             if (mfclock){
365                 mfclock->GetCorrelatedTime(0,&endtime,&dummy);
366                 LONGLONG delay=endtime-starttime;
367                 mediasink->Notify( EC_PROCESSING_LATENCY,(LONG_PTR)&delay,0);
368
369                 //Check if presentation is soon
370                 MFTIME   systime=0;
371                 LONGLONG currenttime=0;
372                 hres=outdatabuffer.pSample->GetSampleTime(&prestime);
373                 if (hres==S_OK) 
374                 {
375                     if (mfclock) mfclock->GetCorrelatedTime(0,&currenttime,&systime);
376                 }
377                 LONGLONG delta=prestime-currenttime; 
378                 if (delta<0) {
379                     break; //break if presentation is soon
380                 }
381
382         
383             }
384         } else break;
385
386     }
387     Unlock();
388 }
389
390 HRESULT STDMETHODCALLTYPE DsAllocator::ProcessMessage(MFVP_MESSAGE_TYPE mess,ULONG_PTR mess_para)
391 {
392     switch (mess) {
393         case MFVP_MESSAGE_FLUSH:{
394             //Log::getInstance()->log("DsAllocator", Log::DEBUG , "EVR Message MFVP_MESSAGE_FLUSH received");
395             FlushEVRSamples(); 
396             start_get_evr_samples=false;
397                                 }break;
398         case MFVP_MESSAGE_INVALIDATEMEDIATYPE: {
399             Log::getInstance()->log("DsAllocator", Log::DEBUG , "EVR Message MFVP_MESSAGE_INVALIDATEMEDIATYPE received");
400             if (mfmediatype) mfmediatype->Release();
401             mfmediatype=NULL;
402             start_get_evr_samples=false;
403             RenegotiateEVRMediaType();}break;
404         case MFVP_MESSAGE_PROCESSINPUTNOTIFY: {
405             Log::getInstance()->log("DsAllocator", Log::DEBUG , "EVR Message MFVP_MESSAGE_PROCESSINPUTNOTIFY received");
406             if (!start_get_evr_samples) GetEVRSamples();
407             start_get_evr_samples=true;
408                                       } break;
409         case MFVP_MESSAGE_BEGINSTREAMING:{
410             Log::getInstance()->log("DsAllocator", Log::DEBUG , "EVR Message MFVP_MESSAGE_BEGINSTREAMING received");
411             ResetSyncOffsets();
412             ((OsdWin*)Osd::getInstance())->setExternalDriving(this,vwidth,vheight);
413             //((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_started);//No need to do this causes misbehaviout
414             endofstream=false;
415                                          }break;
416         case MFVP_MESSAGE_ENDSTREAMING: {
417             Log::getInstance()->log("DsAllocator", Log::DEBUG , "EVR Message MFVP_MESSAGE_ENDSTREAMING received");
418             ((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_off);
419             ((OsdWin*)Osd::getInstance())->setExternalDriving(NULL,vwidth,vheight);
420             start_get_evr_samples=false;
421             //FlushEVRSamples();
422             //if (mfmediatype) mfmediatype->Release();
423             //mfmediatype=NULL;
424                                         } break;
425         case MFVP_MESSAGE_ENDOFSTREAM: {
426             Log::getInstance()->log("DsAllocator", Log::DEBUG , "EVR Message MFVP_MESSAGE_ENDOFSTREAM received");
427             MessageBox(0,"endofstream","endofstream",0);
428             endofstream=true;
429             start_get_evr_samples=false;
430                                        } break;
431         case MFVP_MESSAGE_STEP: {
432             Log::getInstance()->log("DsAllocator", Log::DEBUG , "EVR Message MFVP_MESSAGE_STEP received");
433             ((OsdWin*)Osd::getInstance())->setExternalDriving(this,vwidth,vheight);
434             ((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_pause);
435             MessageBox(0,"steppy","steppy",0);
436             FlushEVRSamples(/*LOWORD(mess_para)*/); //Message sending, has to be done after compeletion
437                                 }; break;
438         case MFVP_MESSAGE_CANCELSTEP: {
439             Log::getInstance()->log("DsAllocator", Log::DEBUG , "EVR Message MFVP_MESSAGE_CANCELSTEP received");
440             //???
441                                       }; break;
442         default:
443             MessageBox(0,"unhandled","unhandled",0);
444     };
445     return S_OK;
446 }
447
448 HRESULT STDMETHODCALLTYPE DsAllocator::OnClockStart(MFTIME systime,LONGLONG startoffset)
449 {
450     //((OsdWin*)Osd::getInstance())->SetEVRTimes(systime,startoffset);
451     timeBeginPeriod(1);
452
453     if (PRESENTATION_CURRENT_POSITION!=startoffset) FlushEVRSamples();
454     ((OsdWin*)Osd::getInstance())->setExternalDriving(this,vwidth,vheight);
455      Log::getInstance()->log("DsAllocator", Log::DEBUG , "OnClockStart");
456     ((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_started);
457     //GetEVRSamples();
458
459     return S_OK;
460 }
461
462 HRESULT STDMETHODCALLTYPE DsAllocator::OnClockStop(MFTIME systime)
463 {
464     timeEndPeriod(1);
465
466     ((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_off);
467     
468      Log::getInstance()->log("DsAllocator", Log::DEBUG , "OnClockStop");
469     ((OsdWin*)Osd::getInstance())->setExternalDriving(NULL,vwidth,vheight);
470     FlushEVRSamples();
471     return S_OK;
472 }
473
474 HRESULT STDMETHODCALLTYPE DsAllocator::OnClockPause(MFTIME systime)
475 {
476     timeEndPeriod(1);
477     ((OsdWin*)Osd::getInstance())->setExternalDriving(this,vwidth,vheight);
478     
479      Log::getInstance()->log("DsAllocator", Log::DEBUG , "OnClockPause");
480     ((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_pause);
481     return S_OK;
482 }
483
484 HRESULT STDMETHODCALLTYPE DsAllocator::OnClockRestart(MFTIME systime)
485 {
486     ((OsdWin*)Osd::getInstance())->setExternalDriving(this,vwidth,vheight);
487     
488      Log::getInstance()->log("DsAllocator", Log::DEBUG , "OnClockRestart");
489     ((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_started);
490
491     return S_OK;
492 }
493
494 HRESULT STDMETHODCALLTYPE DsAllocator::OnClockSetRate(MFTIME systime,float rate)
495 {
496     timeBeginPeriod(1);
497     return S_OK;
498 }
499
500 HRESULT STDMETHODCALLTYPE DsAllocator::GetCurrentMediaType(IMFVideoMediaType **mtype)
501 { MessageBox(0,"mediatype","mediatype",0);
502 if (mtype==NULL) return E_POINTER;
503 Lock();
504 if (mfmediatype==NULL)
505 {
506     Unlock();
507     *mtype=NULL;
508     return MF_E_NOT_INITIALIZED;
509 }
510 HRESULT hres=mfmediatype->QueryInterface(IID_IMFVideoMediaType,(void**)mtype);
511 Unlock();
512 return hres;
513 }
514
515 void DsAllocator::RenegotiateEVRMediaType()
516 {
517     if (!mftransform) {
518         Log::getInstance()->log("DsAllocator", Log::DEBUG , "Cannot renegotiate without transform!");
519         return ;
520     }
521     bool gotcha=false;
522     DWORD index=0;
523
524
525     while (!gotcha) {
526         IMFMediaType *mixtype=NULL;
527         HRESULT hres;
528         if (hres=mftransform->GetOutputAvailableType(0,index++,&mixtype)!=S_OK)
529         {
530             Log::getInstance()->log("DsAllocator", Log::DEBUG , "No more types availiable from EVR %d !",hres);
531             break;
532         }
533
534         //Type check
535         BOOL compressed;
536         mixtype->IsCompressedFormat(&compressed); 
537         if (compressed)
538         {
539             mixtype->Release();
540             continue;
541         }
542         UINT32 helper;
543         mixtype->GetUINT32(MF_MT_INTERLACE_MODE,&helper);
544         if (helper!=MFVideoInterlace_Progressive) {
545             Log::getInstance()->log("DsAllocator", Log::DEBUG , "Skip media type interlaced!");
546             mixtype->Release();
547             continue;
548         }
549         GUID temp;
550         mixtype->GetMajorType(&temp);
551         if (temp!=MEDIATYPE_Video) {
552             Log::getInstance()->log("DsAllocator", Log::DEBUG , "Skip media type no video!");
553             mixtype->Release();
554             continue;
555         }
556         if(mftransform->SetOutputType(0,mixtype,MFT_SET_TYPE_TEST_ONLY)!=S_OK) 
557         {
558             Log::getInstance()->log("DsAllocator", Log::DEBUG , "Skip media type test failed!");
559             mixtype->Release();
560             continue;
561         }
562         //Type is ok!
563
564         gotcha=true;
565
566         Lock();
567         if (mfmediatype) mfmediatype->Release();
568         mfmediatype=NULL;
569
570         mfmediatype=mixtype;
571         AllocateEVRSurfaces();
572         Unlock();
573
574         hres=mftransform->SetOutputType(0,mixtype,0);
575
576
577
578         if (hres!=S_OK) 
579         {
580             Lock();
581             if (mfmediatype) mfmediatype->Release();
582             mfmediatype=NULL;
583             gotcha=false;
584
585             Unlock();
586         }
587
588
589         Log::getInstance()->log("DsAllocator", Log::DEBUG , "Output type set! %d",hres);
590     }
591     if (!gotcha) Log::getInstance()->log("DsAllocator", Log::DEBUG , "No suitable output type!");
592
593
594
595 }
596
597 void DsAllocator::AllocateEVRSurfaces()
598 {
599
600     LARGE_INTEGER temp64;
601     mfmediatype->GetUINT64(MF_MT_FRAME_SIZE, (UINT64*)&temp64);
602     vwidth=temp64.HighPart;
603     vheight=temp64.LowPart;
604     GUID subtype;
605     subtype.Data1=D3DFMT_X8R8G8B8;
606     mfmediatype->GetGUID(MF_MT_SUBTYPE,&subtype);
607     D3DFORMAT format=(D3DFORMAT)subtype.Data1;
608     Log::getInstance()->log("DsAllocator", Log::DEBUG , "Surfaceformat is %d, width %d, height %d",format,vwidth,vheight);
609     format=D3DFMT_X8R8G8B8;
610
611     CleanupSurfaces();
612     Lock();
613     OsdWin* osdwin=(OsdWin*)Osd::getInstance();
614     LPDIRECT3DDEVICE9 d3ddev=osdwin->getD3dDev();
615     osdwin->BeginPainting();
616     surfaces.resize(10);
617     for (int i=0;i<10;i++)
618     {
619         HRESULT hres;
620         LPDIRECT3DSURFACE9 surfy;
621
622         hres=d3ddev->CreateRenderTarget(vwidth,vheight,format,
623             D3DMULTISAMPLE_NONE,0,FALSE,&surfy,NULL);
624         if (hres==S_OK)
625         {
626             surfaces[i]=surfy;
627         }
628         else
629         {
630             surfaces[i]=NULL;
631         }
632     }
633     osdwin->EndPainting();
634
635
636
637     for (int i=0;i<surfaces.size();i++) {
638         if (surfaces[i]!=NULL) 
639         {
640             IMFSample *sample=NULL;
641             ptrMFCreateVideoSampleFromSurface(surfaces[i],&sample);
642             if (sample) emptyevrsamples.push(sample);
643         }
644     }
645     Unlock();
646
647 }
648
649 void DsAllocator::FlushEVRSamples()
650 {
651     Lock();
652     while(fullevrsamples.size()>0)
653     {
654         IMFSample *sample=fullevrsamples.front();
655         fullevrsamples.pop();
656         emptyevrsamples.push(sample);
657     }
658     Unlock();
659 }
660 #define FAC 1
661
662 void DsAllocator::GetNextSurface(LPDIRECT3DSURFACE9* surf,DWORD *waittime)
663 {
664     
665     *surf=NULL;
666     *waittime=10;
667     Lock();
668     if (fullevrsamples.size()==0) {
669         *waittime=1;
670         if (start_get_evr_samples) GetEVRSamples();
671     }
672     //Log::getInstance()->log("DsAllocator", Log::DEBUG , "Enter Get Next Surface");
673     
674     while (fullevrsamples.size()>0) 
675     {
676         //MessageBox(0,"Got a sample","got a sample",0);
677         IMFSample *sample=fullevrsamples.front();
678         LONGLONG prestime=0;
679         MFTIME   systime=0;
680         LONGLONG currenttime=0;
681
682         HRESULT hres=sample->GetSampleTime(&prestime);
683         if (hres==S_OK) 
684         {
685             if (mfclock) mfclock->GetCorrelatedTime(0,&currenttime,&systime);
686         }
687         LONGLONG delta=prestime-currenttime; 
688
689        
690
691         if (delta<-10000*20 && false) { //SkipIT
692             LONGLONG latency=-delta;
693             //mediasink->Notify(EC_SAMPLE_LATENCY,(LONG_PTR) &latency,0);
694             LARGE_INTEGER helper;
695             helper.QuadPart=-delta;
696             Log::getInstance()->log("DsAllocator", Log::DEBUG , "skip 1 frame %d %d prestime %lld",helper.LowPart,helper.HighPart,prestime);
697             CalcSyncOffsets(delta/10000LL);
698             //  emptyevrsamples.size(),fullevrsamples.size());
699             fullevrsamples.pop();
700             emptyevrsamples.push(sample);
701             framesdropped++;
702             continue;
703         }
704
705         if (delta<10000*20 || !mfclock )
706         {
707             *waittime=0;
708             IMFMediaBuffer* buffy=NULL;
709             //MessageBox(0,"its showtime","showtimw",0);
710             CalcSyncOffsets(delta/10000LL);
711             framesdrawn++;
712             hres=sample->GetBufferByIndex(0,&buffy);
713             //LARGE_INTEGER helper;
714             //helper.QuadPart=-delta;
715             //Log::getInstance()->log("DsAllocator", Log::DEBUG , "Paint 1 frame %d %d, frames  %d prestime %lld",
716              //   helper.LowPart,helper.HighPart,fullevrsamples.size(),prestime);
717             if (hres!=S_OK) { //SkipIT
718                 fullevrsamples.pop();
719                 emptyevrsamples.push(sample);
720                 continue;
721             }
722             IMFGetService* service;
723             hres=buffy->QueryInterface(IID_IMFGetService,(void**)&service);
724             buffy->Release();
725             if (hres!=S_OK) { //SkipIT
726                 fullevrsamples.pop();
727                 emptyevrsamples.push(sample);
728                 continue;
729             }
730             LPDIRECT3DSURFACE9 tempsurf;
731             hres=service->GetService(MR_BUFFER_SERVICE,IID_IDirect3DSurface9 ,(void**) &tempsurf);
732             service->Release();
733             if (hres!=S_OK) { //SkipIT
734                 fullevrsamples.pop();
735                 emptyevrsamples.push(sample);
736                 continue;
737             }
738             *surf=tempsurf;
739             break;
740         } else {
741             *waittime=delta/10000-10;
742             *surf=NULL;
743             break;
744         }       
745     }
746
747     Unlock();
748
749 }
750
751 void DsAllocator::DiscardSurfaceandgetWait(DWORD *waittime)
752 {
753     //Log::getInstance()->log("DsAllocator", Log::DEBUG , "Discard surface and get Wait");
754     if (start_get_evr_samples) GetEVRSamples();
755     //Log::getInstance()->log("DsAllocator", Log::DEBUG , "Discard surface and get Wait2");
756     Lock();
757     if (fullevrsamples.size()==0) {
758         *waittime=0;
759         Unlock();
760         return;
761     }
762     IMFSample *sample=fullevrsamples.front();
763     fullevrsamples.pop();
764     emptyevrsamples.push(sample);
765     *waittime=0;
766
767     while (fullevrsamples.size()>0) 
768     {
769
770         IMFSample *sample=fullevrsamples.front();
771         LONGLONG prestime=0;
772         MFTIME   systime=0;
773         LONGLONG currenttime=0;
774
775         HRESULT hres=sample->GetSampleTime(&prestime);
776         if (hres==S_OK) 
777         {
778             if (mfclock) mfclock->GetCorrelatedTime(0,&currenttime,&systime);
779         }
780         LONGLONG delta=prestime-currenttime;
781
782
783         if (delta<-10000*20 ) { //SkipIT
784              LONGLONG latency=-delta;
785            // mediasink->Notify(EC_SAMPLE_LATENCY,(LONG_PTR) &latency,0);
786             //LARGE_INTEGER helper;
787             //helper.QuadPart=-delta;
788             //Log::getInstance()->log("DsAllocator", Log::DEBUG , "skip 1 frame %d %d time %lld",helper.LowPart,helper.HighPart,prestime);
789             CalcSyncOffsets(delta/10000LL);
790             //  emptyevrsamples.size(),fullevrsamples.size());
791             fullevrsamples.pop();
792             emptyevrsamples.push(sample);
793             framesdropped++;
794             continue;
795         }
796
797         *waittime=min(delta/10000/2-10,1); 
798
799         break;
800     }
801     Unlock();
802
803 }
804 void DsAllocator::ResetSyncOffsets()
805 {
806     for (int i=0;i<n_stats;i++)
807     {
808         sync_offset[i]=0;
809         jitter_offset[i]=0;
810     }
811     framesdrawn=0;
812     lastdelframe=0;
813     framesdropped=0;
814     avg_sync_offset=0;
815     dev_sync_offset=0;
816     jitter=0;
817     sync_pos=0;
818     jitter_pos=0;
819     avgfps=0;
820 }
821
822 void DsAllocator::CalcSyncOffsets(int sync)
823 {
824     sync_offset[sync_pos]=sync;
825     sync_pos=(sync_pos +1)%n_stats;
826
827     double mean_value=0;
828     for (int i=0;i<n_stats;i++)
829     {
830         mean_value+=sync_offset[i];
831     }
832     mean_value/=(double) n_stats;
833     double std_dev=0;
834     for (int i=0;i<n_stats;i++)
835     {
836         double temp_dev=(mean_value-(double)sync_offset[i]);
837         std_dev+=temp_dev*temp_dev;
838     }
839     std_dev/=(double)n_stats;
840     avg_sync_offset=mean_value;
841     dev_sync_offset=sqrt(std_dev);
842 }
843
844 void DsAllocator::CalcJitter(int jitter)
845 {
846     jitter_offset[jitter_pos]=jitter;
847     jitter_pos=(jitter_pos +1)%n_stats;
848     
849
850     double mean_value=0;
851     for (int i=0;i<n_stats;i++)
852     {
853         mean_value+=jitter_offset[i];
854     }
855     mean_value/=(double) n_stats;
856     avgfps=1000./mean_value*100.;
857     double std_dev=0;
858     for (int i=0;i<n_stats;i++)
859     {
860         double temp_dev=(mean_value-(double)jitter_offset[i]);
861         std_dev+=temp_dev*temp_dev;
862     }
863     std_dev/=(double)n_stats;
864     jitter=sqrt(std_dev);
865 }
866
867
868 HRESULT STDMETHODCALLTYPE DsAllocator::get_FramesDrawn(int *val)
869 {
870     *val=framesdrawn;
871     return S_OK;
872 }
873
874 HRESULT STDMETHODCALLTYPE DsAllocator::get_AvgFrameRate(int *val)
875 {
876     *val=avgfps;
877     return S_OK;
878 }
879
880 HRESULT STDMETHODCALLTYPE DsAllocator::get_Jitter(int *val)
881 {
882     *val=jitter;
883     return S_OK;
884 }
885
886 HRESULT STDMETHODCALLTYPE DsAllocator::get_AvgSyncOffset(int *val)
887 {
888     *val=avg_sync_offset;
889     return S_OK;
890 }
891
892 HRESULT STDMETHODCALLTYPE DsAllocator::get_DevSyncOffset(int *val)
893 {
894     *val=dev_sync_offset;
895     return S_OK;
896 }
897 HRESULT STDMETHODCALLTYPE DsAllocator::get_FramesDroppedInRenderer(int *val)
898 {
899     *val=framesdropped;
900     return S_OK;
901 }