]> git.vomp.tv Git - vompclient.git/blob - dsallocator.cc
Fix live TV ac3 playback, probably a very old bug
[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())->SetEVRStatus(OsdWin::EVR_pres_off);
54     ((OsdWin*)Osd::getInstance())->setExternalDriving(NULL,vwidth,vheight);
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     Lock();
290     MFCLOCK_STATE clockstate;
291     if (mfclock) mfclock->GetState(0,&clockstate);
292     //MessageBox(0,"get samples","samples",0);
293     
294     if (mfclock && clockstate==MFCLOCK_STATE_STOPPED && fullevrsamples.size()>0)
295     {
296         Unlock();
297         return;
298     }
299
300     while (emptyevrsamples.size()>0)
301     {
302
303         MFT_OUTPUT_DATA_BUFFER outdatabuffer;
304         ZeroMemory(&outdatabuffer,sizeof(outdatabuffer));
305         outdatabuffer.pSample=emptyevrsamples.front();
306         DWORD status=0;
307         LONGLONG starttime,endtime;
308         MFTIME dummy;
309         starttime=0;
310         endtime=0;
311
312         if (mfclock) 
313         {
314             mfclock->GetCorrelatedTime(0,&starttime,&dummy);
315             if (lastdelframe) CalcJitter( (starttime-lastdelframe)/10000);
316             lastdelframe=starttime;
317         }
318
319         HRESULT hres=mftransform->ProcessOutput(0,1,&outdatabuffer,&status);
320         
321
322         if (hres==MF_E_TRANSFORM_NEED_MORE_INPUT)
323         {
324             if (endofstream)
325             {
326
327                 endofstream=false;
328                 mediasink->Notify(EC_COMPLETE,(LONG_PTR) S_OK,0);
329
330             }
331             break;
332         }
333         else if (hres==MF_E_TRANSFORM_STREAM_CHANGE)
334         {
335             if (mfmediatype) mfmediatype->Release();
336             mfmediatype=NULL;
337             break;
338         } 
339         else if (hres==MF_E_TRANSFORM_TYPE_NOT_SET)
340         {
341             if (mfmediatype) mfmediatype->Release();
342             mfmediatype=NULL;
343             RenegotiateEVRMediaType();
344             break;
345         } 
346         else if (hres==S_OK)
347         {
348             LONGLONG prestime=0;
349             hres=outdatabuffer.pSample->GetSampleTime(&prestime);
350             //Log::getInstance()->log("DsAllocator", Log::DEBUG , "Got EVR Sample %lld",prestime);
351             IMFSample *temp=emptyevrsamples.front();
352             emptyevrsamples.pop();
353
354
355
356             fullevrsamples.push(temp);
357             //Log::getInstance()->log("DsAllocator", Log::DEBUG , "got evr sample %d, %d",
358             //  emptyevrsamples.size(),fullevrsamples.size());
359             if (mfclock){
360                 mfclock->GetCorrelatedTime(0,&endtime,&dummy);
361                 LONGLONG delay=endtime-starttime;
362                 mediasink->Notify( EC_PROCESSING_LATENCY,(LONG_PTR)&delay,0);
363             }
364         } else break;
365
366     }
367     Unlock();
368 }
369
370 HRESULT STDMETHODCALLTYPE DsAllocator::ProcessMessage(MFVP_MESSAGE_TYPE mess,ULONG_PTR mess_para)
371 {
372     switch (mess) {
373         case MFVP_MESSAGE_FLUSH:{
374             //Log::getInstance()->log("DsAllocator", Log::DEBUG , "EVR Message MFVP_MESSAGE_FLUSH received");
375             FlushEVRSamples(); }break;
376         case MFVP_MESSAGE_INVALIDATEMEDIATYPE: {
377             Log::getInstance()->log("DsAllocator", Log::DEBUG , "EVR Message MFVP_MESSAGE_INVALIDATEMEDIATYPE received");
378             if (mfmediatype) mfmediatype->Release();
379             mfmediatype=NULL;
380             RenegotiateEVRMediaType();}break;
381         case MFVP_MESSAGE_PROCESSINPUTNOTIFY: {
382             //Log::getInstance()->log("DsAllocator", Log::DEBUG , "EVR Message MFVP_MESSAGE_PROCESSINPUTNOTIFY received");
383             GetEVRSamples(); } break;
384         case MFVP_MESSAGE_BEGINSTREAMING:{
385             Log::getInstance()->log("DsAllocator", Log::DEBUG , "EVR Message MFVP_MESSAGE_BEGINSTREAMING received");
386             ResetSyncOffsets();
387             ((OsdWin*)Osd::getInstance())->setExternalDriving(this,vwidth,vheight);
388             //((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_started);//No need to do this causes misbehaviout
389             endofstream=false;
390                                          }break;
391         case MFVP_MESSAGE_ENDSTREAMING: {
392             Log::getInstance()->log("DsAllocator", Log::DEBUG , "EVR Message MFVP_MESSAGE_ENDSTREAMING received");
393             ((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_off);
394             ((OsdWin*)Osd::getInstance())->setExternalDriving(NULL,vwidth,vheight);
395             //FlushEVRSamples();
396             //if (mfmediatype) mfmediatype->Release();
397             //mfmediatype=NULL;
398                                         } break;
399         case MFVP_MESSAGE_ENDOFSTREAM: {
400             Log::getInstance()->log("DsAllocator", Log::DEBUG , "EVR Message MFVP_MESSAGE_ENDOFSTREAM received");
401             MessageBox(0,"endofstream","endofstream",0);
402             endofstream=true;
403                                        } break;
404         case MFVP_MESSAGE_STEP: {
405             Log::getInstance()->log("DsAllocator", Log::DEBUG , "EVR Message MFVP_MESSAGE_STEP received");
406             ((OsdWin*)Osd::getInstance())->setExternalDriving(this,vwidth,vheight);
407             ((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_pause);
408             MessageBox(0,"steppy","steppy",0);
409             FlushEVRSamples(/*LOWORD(mess_para)*/); //Message sending, has to be done after compeletion
410                                 }; break;
411         case MFVP_MESSAGE_CANCELSTEP: {
412             Log::getInstance()->log("DsAllocator", Log::DEBUG , "EVR Message MFVP_MESSAGE_CANCELSTEP received");
413             //???
414                                       }; break;
415         default:
416             MessageBox(0,"unhandled","unhandled",0);
417     };
418     return S_OK;
419 }
420
421 HRESULT STDMETHODCALLTYPE DsAllocator::OnClockStart(MFTIME systime,LONGLONG startoffset)
422 {
423     //((OsdWin*)Osd::getInstance())->SetEVRTimes(systime,startoffset);
424     timeBeginPeriod(1);
425
426     if (PRESENTATION_CURRENT_POSITION!=startoffset) FlushEVRSamples();
427     ((OsdWin*)Osd::getInstance())->setExternalDriving(this,vwidth,vheight);
428      Log::getInstance()->log("DsAllocator", Log::DEBUG , "OnClockStart");
429     ((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_started);
430     GetEVRSamples();
431
432     return S_OK;
433 }
434
435 HRESULT STDMETHODCALLTYPE DsAllocator::OnClockStop(MFTIME systime)
436 {
437     timeEndPeriod(1);
438
439     ((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_off);
440     
441      Log::getInstance()->log("DsAllocator", Log::DEBUG , "OnClockStop");
442     ((OsdWin*)Osd::getInstance())->setExternalDriving(NULL,vwidth,vheight);
443     FlushEVRSamples();
444     return S_OK;
445 }
446
447 HRESULT STDMETHODCALLTYPE DsAllocator::OnClockPause(MFTIME systime)
448 {
449     timeEndPeriod(1);
450     ((OsdWin*)Osd::getInstance())->setExternalDriving(this,vwidth,vheight);
451     
452      Log::getInstance()->log("DsAllocator", Log::DEBUG , "OnClockPause");
453     ((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_pause);
454     return S_OK;
455 }
456
457 HRESULT STDMETHODCALLTYPE DsAllocator::OnClockRestart(MFTIME systime)
458 {
459     ((OsdWin*)Osd::getInstance())->setExternalDriving(this,vwidth,vheight);
460     
461      Log::getInstance()->log("DsAllocator", Log::DEBUG , "OnClockRestart");
462     ((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_started);
463
464     return S_OK;
465 }
466
467 HRESULT STDMETHODCALLTYPE DsAllocator::OnClockSetRate(MFTIME systime,float rate)
468 {
469     timeBeginPeriod(1);
470     return S_OK;
471 }
472
473 HRESULT STDMETHODCALLTYPE DsAllocator::GetCurrentMediaType(IMFVideoMediaType **mtype)
474 { MessageBox(0,"mediatype","mediatype",0);
475 if (mtype==NULL) return E_POINTER;
476 Lock();
477 if (mfmediatype==NULL)
478 {
479     Unlock();
480     *mtype=NULL;
481     return MF_E_NOT_INITIALIZED;
482 }
483 HRESULT hres=mfmediatype->QueryInterface(IID_IMFVideoMediaType,(void**)mtype);
484 Unlock();
485 return hres;
486 }
487
488 void DsAllocator::RenegotiateEVRMediaType()
489 {
490     if (!mftransform) {
491         Log::getInstance()->log("DsAllocator", Log::DEBUG , "Cannot renegotiate without transform!");
492         return ;
493     }
494     bool gotcha=false;
495     DWORD index=0;
496
497
498     while (!gotcha) {
499         IMFMediaType *mixtype=NULL;
500         HRESULT hres;
501         if (hres=mftransform->GetOutputAvailableType(0,index++,&mixtype)!=S_OK)
502         {
503             Log::getInstance()->log("DsAllocator", Log::DEBUG , "No more types availiable from EVR %d !",hres);
504             break;
505         }
506
507         //Type check
508         BOOL compressed;
509         mixtype->IsCompressedFormat(&compressed); 
510         if (compressed)
511         {
512             mixtype->Release();
513             continue;
514         }
515         UINT32 helper;
516         mixtype->GetUINT32(MF_MT_INTERLACE_MODE,&helper);
517         if (helper!=MFVideoInterlace_Progressive) {
518             Log::getInstance()->log("DsAllocator", Log::DEBUG , "Skip media type interlaced!");
519             mixtype->Release();
520             continue;
521         }
522         GUID temp;
523         mixtype->GetMajorType(&temp);
524         if (temp!=MEDIATYPE_Video) {
525             Log::getInstance()->log("DsAllocator", Log::DEBUG , "Skip media type no video!");
526             mixtype->Release();
527             continue;
528         }
529         if(mftransform->SetOutputType(0,mixtype,MFT_SET_TYPE_TEST_ONLY)!=S_OK) 
530         {
531             Log::getInstance()->log("DsAllocator", Log::DEBUG , "Skip media type test failed!");
532             mixtype->Release();
533             continue;
534         }
535         //Type is ok!
536
537         gotcha=true;
538
539         Lock();
540         if (mfmediatype) mfmediatype->Release();
541         mfmediatype=NULL;
542
543         mfmediatype=mixtype;
544         AllocateEVRSurfaces();
545         Unlock();
546
547         hres=mftransform->SetOutputType(0,mixtype,0);
548
549
550
551         if (hres!=S_OK) 
552         {
553             Lock();
554             if (mfmediatype) mfmediatype->Release();
555             mfmediatype=NULL;
556             gotcha=false;
557
558             Unlock();
559         }
560
561
562         Log::getInstance()->log("DsAllocator", Log::DEBUG , "Output type set! %d",hres);
563     }
564     if (!gotcha) Log::getInstance()->log("DsAllocator", Log::DEBUG , "No suitable output type!");
565
566
567
568 }
569
570 void DsAllocator::AllocateEVRSurfaces()
571 {
572
573     LARGE_INTEGER temp64;
574     mfmediatype->GetUINT64(MF_MT_FRAME_SIZE, (UINT64*)&temp64);
575     vwidth=temp64.HighPart;
576     vheight=temp64.LowPart;
577     GUID subtype;
578     subtype.Data1=D3DFMT_X8R8G8B8;
579     mfmediatype->GetGUID(MF_MT_SUBTYPE,&subtype);
580     D3DFORMAT format=(D3DFORMAT)subtype.Data1;
581     Log::getInstance()->log("DsAllocator", Log::DEBUG , "Surfaceformat is %d, width %d, height %d",format,vwidth,vheight);
582     format=D3DFMT_X8R8G8B8;
583
584     CleanupSurfaces();
585     Lock();
586     OsdWin* osdwin=(OsdWin*)Osd::getInstance();
587     LPDIRECT3DDEVICE9 d3ddev=osdwin->getD3dDev();
588     osdwin->BeginPainting();
589     surfaces.resize(10);
590     for (int i=0;i<10;i++)
591     {
592         HRESULT hres;
593         LPDIRECT3DSURFACE9 surfy;
594
595         hres=d3ddev->CreateRenderTarget(vwidth,vheight,format,
596             D3DMULTISAMPLE_NONE,0,FALSE,&surfy,NULL);
597         if (hres==S_OK)
598         {
599             surfaces[i]=surfy;
600         }
601         else
602         {
603             surfaces[i]=NULL;
604         }
605     }
606     osdwin->EndPainting();
607
608
609
610     for (int i=0;i<surfaces.size();i++) {
611         if (surfaces[i]!=NULL) 
612         {
613             IMFSample *sample=NULL;
614             ptrMFCreateVideoSampleFromSurface(surfaces[i],&sample);
615             if (sample) emptyevrsamples.push(sample);
616         }
617     }
618     Unlock();
619
620 }
621
622 void DsAllocator::FlushEVRSamples()
623 {
624     Lock();
625     while(fullevrsamples.size()>0)
626     {
627         IMFSample *sample=fullevrsamples.front();
628         fullevrsamples.pop();
629         emptyevrsamples.push(sample);
630     }
631     Unlock();
632 }
633 #define FAC 1
634
635 void DsAllocator::GetNextSurface(LPDIRECT3DSURFACE9* surf,DWORD *waittime)
636 {
637     
638     *surf=NULL;
639     *waittime=10;
640     if (fullevrsamples.size()==0) GetEVRSamples();
641     Lock();
642     //Log::getInstance()->log("DsAllocator", Log::DEBUG , "Enter Get Next Surface");
643     
644     while (fullevrsamples.size()>0) 
645     {
646         //MessageBox(0,"Got a sample","got a sample",0);
647         IMFSample *sample=fullevrsamples.front();
648         LONGLONG prestime=0;
649         MFTIME   systime=0;
650         LONGLONG currenttime=0;
651
652         HRESULT hres=sample->GetSampleTime(&prestime);
653         if (hres==S_OK) 
654         {
655             if (mfclock) mfclock->GetCorrelatedTime(0,&currenttime,&systime);
656         }
657         LONGLONG delta=prestime-currenttime; 
658
659        
660
661         if (delta<-10000*20 && false) { //SkipIT
662             LONGLONG latency=-delta;
663             //mediasink->Notify(EC_SAMPLE_LATENCY,(LONG_PTR) &latency,0);
664             LARGE_INTEGER helper;
665             helper.QuadPart=-delta;
666             Log::getInstance()->log("DsAllocator", Log::DEBUG , "skip 1 frame %d %d prestime %lld",helper.LowPart,helper.HighPart,prestime);
667             CalcSyncOffsets(delta/10000LL);
668             //  emptyevrsamples.size(),fullevrsamples.size());
669             fullevrsamples.pop();
670             emptyevrsamples.push(sample);
671             framesdropped++;
672             continue;
673         }
674
675         if (delta<10000*20 || !mfclock )
676         {
677             *waittime=0;
678             IMFMediaBuffer* buffy=NULL;
679             //MessageBox(0,"its showtime","showtimw",0);
680             CalcSyncOffsets(delta/10000LL);
681             framesdrawn++;
682             hres=sample->GetBufferByIndex(0,&buffy);
683             //LARGE_INTEGER helper;
684             //helper.QuadPart=-delta;
685             //Log::getInstance()->log("DsAllocator", Log::DEBUG , "Paint 1 frame %d %d, frames  %d prestime %lld",
686              //   helper.LowPart,helper.HighPart,fullevrsamples.size(),prestime);
687             if (hres!=S_OK) { //SkipIT
688                 fullevrsamples.pop();
689                 emptyevrsamples.push(sample);
690                 continue;
691             }
692             IMFGetService* service;
693             hres=buffy->QueryInterface(IID_IMFGetService,(void**)&service);
694             buffy->Release();
695             if (hres!=S_OK) { //SkipIT
696                 fullevrsamples.pop();
697                 emptyevrsamples.push(sample);
698                 continue;
699             }
700             LPDIRECT3DSURFACE9 tempsurf;
701             hres=service->GetService(MR_BUFFER_SERVICE,IID_IDirect3DSurface9 ,(void**) &tempsurf);
702             service->Release();
703             if (hres!=S_OK) { //SkipIT
704                 fullevrsamples.pop();
705                 emptyevrsamples.push(sample);
706                 continue;
707             }
708             *surf=tempsurf;
709             break;
710         } else {
711             *waittime=delta/10000-10;
712             *surf=NULL;
713             break;
714         }       
715     }
716
717     Unlock();
718
719 }
720
721 void DsAllocator::DiscardSurfaceandgetWait(DWORD *waittime)
722 {
723     //Log::getInstance()->log("DsAllocator", Log::DEBUG , "Discard surface and get Wait");
724     GetEVRSamples();
725     //Log::getInstance()->log("DsAllocator", Log::DEBUG , "Discard surface and get Wait2");
726     Lock();
727     if (fullevrsamples.size()==0) {
728         *waittime=0;
729         Unlock();
730         return;
731     }
732     IMFSample *sample=fullevrsamples.front();
733     fullevrsamples.pop();
734     emptyevrsamples.push(sample);
735     *waittime=0;
736
737     while (fullevrsamples.size()>0) 
738     {
739
740         IMFSample *sample=fullevrsamples.front();
741         LONGLONG prestime=0;
742         MFTIME   systime=0;
743         LONGLONG currenttime=0;
744
745         HRESULT hres=sample->GetSampleTime(&prestime);
746         if (hres==S_OK) 
747         {
748             if (mfclock) mfclock->GetCorrelatedTime(0,&currenttime,&systime);
749         }
750         LONGLONG delta=prestime-currenttime;
751
752
753         if (delta<-10000*20 ) { //SkipIT
754              LONGLONG latency=-delta;
755            // mediasink->Notify(EC_SAMPLE_LATENCY,(LONG_PTR) &latency,0);
756             //LARGE_INTEGER helper;
757             //helper.QuadPart=-delta;
758             //Log::getInstance()->log("DsAllocator", Log::DEBUG , "skip 1 frame %d %d time %lld",helper.LowPart,helper.HighPart,prestime);
759             CalcSyncOffsets(delta/10000LL);
760             //  emptyevrsamples.size(),fullevrsamples.size());
761             fullevrsamples.pop();
762             emptyevrsamples.push(sample);
763             framesdropped++;
764             continue;
765         }
766
767         *waittime=min(delta/10000/2-10,1); 
768
769         break;
770     }
771     Unlock();
772
773 }
774 void DsAllocator::ResetSyncOffsets()
775 {
776     for (int i=0;i<n_stats;i++)
777     {
778         sync_offset[i]=0;
779         jitter_offset[i]=0;
780     }
781     framesdrawn=0;
782     lastdelframe=0;
783     framesdropped=0;
784     avg_sync_offset=0;
785     dev_sync_offset=0;
786     jitter=0;
787     sync_pos=0;
788     jitter_pos=0;
789     avgfps=0;
790 }
791
792 void DsAllocator::CalcSyncOffsets(int sync)
793 {
794     sync_offset[sync_pos]=sync;
795     sync_pos=(sync_pos +1)%n_stats;
796
797     double mean_value=0;
798     for (int i=0;i<n_stats;i++)
799     {
800         mean_value+=sync_offset[i];
801     }
802     mean_value/=(double) n_stats;
803     double std_dev=0;
804     for (int i=0;i<n_stats;i++)
805     {
806         double temp_dev=(mean_value-(double)sync_offset[i]);
807         std_dev+=temp_dev*temp_dev;
808     }
809     std_dev/=(double)n_stats;
810     avg_sync_offset=mean_value;
811     dev_sync_offset=sqrt(std_dev);
812 }
813
814 void DsAllocator::CalcJitter(int jitter)
815 {
816     jitter_offset[jitter_pos]=jitter;
817     jitter_pos=(jitter_pos +1)%n_stats;
818     
819
820     double mean_value=0;
821     for (int i=0;i<n_stats;i++)
822     {
823         mean_value+=jitter_offset[i];
824     }
825     mean_value/=(double) n_stats;
826     avgfps=1000./mean_value*100.;
827     double std_dev=0;
828     for (int i=0;i<n_stats;i++)
829     {
830         double temp_dev=(mean_value-(double)jitter_offset[i]);
831         std_dev+=temp_dev*temp_dev;
832     }
833     std_dev/=(double)n_stats;
834     jitter=sqrt(std_dev);
835 }
836
837
838 HRESULT STDMETHODCALLTYPE DsAllocator::get_FramesDrawn(int *val)
839 {
840     *val=framesdrawn;
841     return S_OK;
842 }
843
844 HRESULT STDMETHODCALLTYPE DsAllocator::get_AvgFrameRate(int *val)
845 {
846     *val=avgfps;
847     return S_OK;
848 }
849
850 HRESULT STDMETHODCALLTYPE DsAllocator::get_Jitter(int *val)
851 {
852     *val=jitter;
853     return S_OK;
854 }
855
856 HRESULT STDMETHODCALLTYPE DsAllocator::get_AvgSyncOffset(int *val)
857 {
858     *val=avg_sync_offset;
859     return S_OK;
860 }
861
862 HRESULT STDMETHODCALLTYPE DsAllocator::get_DevSyncOffset(int *val)
863 {
864     *val=dev_sync_offset;
865     return S_OK;
866 }
867 HRESULT STDMETHODCALLTYPE DsAllocator::get_FramesDroppedInRenderer(int *val)
868 {
869     *val=framesdropped;
870     return S_OK;
871 }