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