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