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