2 Copyright 2004-2005 Chris Tallon
\r
4 This file is part of VOMP.
\r
6 VOMP is free software; you can redistribute it and/or modify
\r
7 it under the terms of the GNU General Public License as published by
\r
8 the Free Software Foundation; either version 2 of the License, or
\r
9 (at your option) any later version.
\r
11 VOMP is distributed in the hope that it will be useful,
\r
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
14 GNU General Public License for more details.
\r
16 You should have received a copy of the GNU General Public License
\r
17 along with VOMP; if not, write to the Free Software
\r
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
\r
23 #include "videowin.h"
\r
25 #include "dssourcefilter.h"
\r
26 #include "dsallocator.h"
\r
29 #include "audiowin.h"
\r
30 #include "wwinvideofilter.h"
\r
31 #include "wwinvideoh264filter.h"
\r
32 #include "wtabbar.h"
\r
33 #include "woptionpane.h"
\r
35 #include "demuxer.h"
\r
38 #include <mferror.h>
\r
40 void AdjustWindow();
\r
44 VideoWin::VideoWin()
\r
47 dsgraphbuilder=NULL;
\r
48 dsmediacontrol=NULL;
\r
56 lastaudiomode=MPTYPE_MPEG_AUDIO;
\r
57 //lastaudiomode=MPTYPE_AC3;
\r
58 dsvmrsurfnotify=NULL;
\r
59 filtermutex=CreateMutex(NULL,FALSE,NULL);
\r
61 offsetvideonotset=true;
\r
62 offsetaudionotset=true;
\r
69 cur_audio_media_sample=NULL;
\r
70 cur_video_media_sample=NULL;
\r
77 aud_type=Audio::MPEG2_PES;
\r
78 iframemode=false;//We are not in Iframe mode at begining
\r
79 vmrdeinterlacing=2;//Best
\r
80 videofilterselected=-1;
\r
81 videoH264filterselected=-1;
\r
82 OSVERSIONINFO verinfo;
\r
83 verinfo.dwOSVersionInfoSize=sizeof(verinfo);
\r
84 GetVersionEx(&verinfo);
\r
86 if (verinfo.dwMajorVersion>=6) {
\r
87 currentpresenter=EVR;
\r
89 currentpresenter=VMR9;
\r
91 videoH264dtsfix=false;
\r
92 videompeg2dtsfix=false;
\r
99 VideoWin::~VideoWin()
\r
102 CloseHandle(filtermutex);
\r
104 for (i=0;i<videofilterlist.size();i++)
\r
106 if (videofilterlist[i].displayname) delete [] videofilterlist[i].displayname;
\r
107 if (videofilterlist[i].friendlyname) delete [] videofilterlist[i].friendlyname;
\r
109 videofilterlist.clear();
\r
111 for (i=0;i<videoH264filterlist.size();i++)
\r
113 if (videoH264filterlist[i].displayname) delete [] videoH264filterlist[i].displayname;
\r
114 if (videoH264filterlist[i].friendlyname) delete [] videoH264filterlist[i].friendlyname;
\r
116 videoH264filterlist.clear();
\r
124 int VideoWin::init(UCHAR tformat)
\r
126 if (initted) return 0;
\r
129 tvsize=Video::ASPECT16X9; //Internally Vomp should think we are a 16:9 TV
\r
132 initFilterDatabase();
\r
133 initH264FilterDatabase();
\r
135 if (!setFormat(tformat)){ shutdown(); return 0; }
\r
141 int VideoWin::setTVsize(UCHAR ttvsize)
\r
143 pseudotvsize=ttvsize;
\r
147 int VideoWin::setDefaultAspect()
\r
149 return setAspectRatio(Video::ASPECT4X3);
\r
152 int VideoWin::shutdown()
\r
154 if (!initted) return 0;
\r
159 int VideoWin::setFormat(UCHAR tformat)
\r
161 if (!initted) return 0;
\r
162 if ((tformat != PAL) && (tformat != NTSC)) return 0;
\r
164 if (format == NTSC)
\r
167 screenHeight = 480;
\r
172 screenHeight = 576;
\r
178 int VideoWin::setConnection(UCHAR tconnection)
\r
180 if (!initted) return 0;
\r
181 if ((tconnection != COMPOSITERGB) && (tconnection != SVIDEO)) return 0;
\r
182 connection = tconnection;
\r
187 int VideoWin::setAspectRatio(UCHAR taspectRatio)
\r
189 if (!initted) return 0;
\r
190 if ((taspectRatio != ASPECT4X3) && (taspectRatio != ASPECT16X9)) return 0;
\r
191 aspectRatio = taspectRatio;
\r
196 int VideoWin::setMode(UCHAR tmode)
\r
198 if (!initted) return 0;
\r
200 //if ((tmode == LETTERBOX) && (tvsize == ASPECT16X9)) return 0; // invalid mode
\r
202 if ((tmode != NORMAL) && (tmode != LETTERBOX) && (tmode != UNKNOWN2) && (tmode != QUARTER) && (tmode != EIGHTH)
\r
203 && (tmode != ZOOM) && (tmode != UNKNOWN6)) return 0;
\r
212 int VideoWin::signalOff()
\r
217 int VideoWin::signalOn()
\r
222 int VideoWin::setSource()
\r
224 if (!initted) return 0;
\r
229 int VideoWin::setPosition(int x, int y)
\r
231 if (!initted) return 0;
\r
232 if (mode==QUARTER || mode==EIGHTH) {
\r
239 int VideoWin::sync()
\r
241 if (!initted) return 0;
\r
245 void VideoWin::initFilterDatabase()
\r
247 /* This method should determine all availiable DirectShow Filters */
\r
248 IFilterMapper2* filtmap=NULL;
\r
250 result = CoCreateInstance(CLSID_FilterMapper2,NULL,CLSCTX_INPROC,
\r
251 IID_IFilterMapper2,(void**)&filtmap);
\r
252 if (result != S_OK)
\r
254 Log::getInstance()->log("VideoWin", Log::ERR , "Unable to create FilterMapper!");
\r
257 /* Wishlist, what Mediatypes do we want */
\r
258 GUID mtypesin[]={MEDIATYPE_Video,MEDIASUBTYPE_MPEG2_VIDEO};
\r
259 IEnumMoniker *myenum;
\r
260 result = filtmap->EnumMatchingFilters(&myenum,0,TRUE,MERIT_DO_NOT_USE+1,
\r
261 TRUE,1,mtypesin,NULL,NULL,FALSE,TRUE,0,NULL,NULL,NULL);
\r
262 if (result != S_OK)
\r
264 filtmap->Release();
\r
265 Log::getInstance()->log("VideoWin", Log::ERR , "Unable to enum Filters!");
\r
270 while(myenum->Next(1,&moni,&gethowmany)==S_OK)
\r
272 VideoFilterDesc desc;
\r
273 ZeroMemory(&desc,sizeof(desc));
\r
276 moni->GetDisplayName(0,0,&string);
\r
277 desc.displayname=new char[wcslen(string)+1];
\r
278 wcstombs(desc.displayname,string,wcslen(string)+1);
\r
279 CoTaskMemFree(string);
\r
281 if (moni->BindToStorage(0,0,IID_IPropertyBag,(void**)&bag) == S_OK)
\r
284 VariantInit(&vari);
\r
285 result = bag->Read(L"FriendlyName",&vari,NULL);
\r
286 if (result == S_OK)
\r
288 desc.friendlyname=new char[wcslen(vari.bstrVal)+1];
\r
289 wcstombs(desc.friendlyname,vari.bstrVal,wcslen(vari.bstrVal)+1);
\r
291 VariantClear(&vari);
\r
297 videofilterlist.push_back(desc);
\r
302 // bctx->Release();
\r
305 videofilterselected=-1;
\r
313 filtmap->Release();
\r
316 void VideoWin::initH264FilterDatabase()
\r
318 /* This method should determine all availiable DirectShow Filters */
\r
319 IFilterMapper2* filtmap=NULL;
\r
321 result = CoCreateInstance(CLSID_FilterMapper2,NULL,CLSCTX_INPROC,
\r
322 IID_IFilterMapper2,(void**)&filtmap);
\r
323 if (result != S_OK)
\r
325 Log::getInstance()->log("VideoWin", Log::ERR , "Unable to create FilterMapper!");
\r
328 /* Wishlist, what Mediatypes do we want */
\r
329 GUID mtypesin[]={MEDIATYPE_Video,MEDIASUBTYPE_H264};
\r
330 IEnumMoniker *myenum;
\r
331 result = filtmap->EnumMatchingFilters(&myenum,0,TRUE,MERIT_DO_NOT_USE+1,
\r
332 TRUE,1,mtypesin,NULL,NULL,FALSE,TRUE,0,NULL,NULL,NULL);
\r
333 if (result != S_OK)
\r
335 filtmap->Release();
\r
336 Log::getInstance()->log("VideoWin", Log::ERR , "Unable to enum Filters!");
\r
341 while(myenum->Next(1,&moni,&gethowmany)==S_OK)
\r
343 VideoFilterDesc desc;
\r
344 ZeroMemory(&desc,sizeof(desc));
\r
347 moni->GetDisplayName(0,0,&string);
\r
348 desc.displayname=new char[wcslen(string)+1];
\r
349 wcstombs(desc.displayname,string,wcslen(string)+1);
\r
350 CoTaskMemFree(string);
\r
352 if (moni->BindToStorage(0,0,IID_IPropertyBag,(void**)&bag) == S_OK)
\r
355 VariantInit(&vari);
\r
356 result = bag->Read(L"FriendlyName",&vari,NULL);
\r
357 if (result == S_OK)
\r
359 desc.friendlyname=new char[wcslen(vari.bstrVal)+1];
\r
360 wcstombs(desc.friendlyname,vari.bstrVal,wcslen(vari.bstrVal)+1);
\r
362 VariantClear(&vari);
\r
368 videoH264filterlist.push_back(desc);
\r
373 // bctx->Release();
\r
376 videoH264filterselected=-1;
\r
384 filtmap->Release();
\r
387 bool VideoWin::loadOptionsfromServer(VDR* vdr)
\r
389 char *name=vdr->configLoad("DirectShow","VideoFilter");
\r
393 for (int i = 0;i <videofilterlist.size();i++)
\r
395 if (strcmp(name,videofilterlist[i].displayname)==0)
\r
397 videofilterselected = i;
\r
402 name=vdr->configLoad("DirectShow","VideoH264Filter");
\r
406 for (int i = 0;i <videoH264filterlist.size();i++)
\r
408 if (strcmp(name,videoH264filterlist[i].displayname)==0)
\r
410 videoH264filterselected = i;
\r
415 name=vdr->configLoad("DirectShow","VMR9DeinterlacingMode");
\r
418 if (STRCASECMP(name,"NoMix")==0) {
\r
419 vmrdeinterlacing=0;
\r
420 } else if (STRCASECMP(name,"None")==0) {
\r
421 vmrdeinterlacing=1;
\r
422 } else if (STRCASECMP(name,"Best")==0) {
\r
423 vmrdeinterlacing=2;
\r
424 } else if (STRCASECMP(name,"Bob")==0) {
\r
425 vmrdeinterlacing=3;
\r
426 } else if (STRCASECMP(name,"Weave")==0) {
\r
427 vmrdeinterlacing=4;
\r
431 name=vdr->configLoad("DirectShow", "VideoPresenter");
\r
433 if (STRCASECMP(name,"VMR9")==0) {
\r
434 currentpresenter=VMR9;
\r
435 } else if (STRCASECMP(name,"EVR")==0) {
\r
436 currentpresenter=EVR;
\r
439 if (!((OsdWin*)Osd::getInstance())->IsEvrSupported()) {
\r
440 currentpresenter=VMR9;
\r
443 name=vdr->configLoad("DirectShow","videoH264dtsfix");
\r
445 if (STRCASECMP(name,"YES")==0) {
\r
446 videoH264dtsfix=true;
\r
448 videoH264dtsfix=false;
\r
451 name=vdr->configLoad("DirectShow","videompeg2dtsfix");
\r
453 if (STRCASECMP(name,"YES")==0) {
\r
454 videompeg2dtsfix=true;
\r
456 videompeg2dtsfix=false;
\r
460 name=vdr->configLoad("DirectGraphics", "StretchFiltering");
\r
462 if (STRCASECMP(name,"None")==0) {
\r
463 ((OsdWin*)Osd::getInstance())->setFilterType(D3DTEXF_NONE);
\r
464 } else if (STRCASECMP(name,"Point")==0) {
\r
465 ((OsdWin*)Osd::getInstance())->setFilterType(D3DTEXF_POINT);
\r
466 } else if (STRCASECMP(name,"Linear")==0) {
\r
467 ((OsdWin*)Osd::getInstance())->setFilterType(D3DTEXF_LINEAR);
\r
478 bool VideoWin::handleOptionChanges(Option* option)
\r
480 if( Video::handleOptionChanges(option)) return true;
\r
481 switch(option->id) {
\r
483 if (STRCASECMP(option->options[option->userSetChoice],"None")==0) {
\r
484 ((OsdWin*)Osd::getInstance())->setFilterType(D3DTEXF_NONE);
\r
485 } else if (STRCASECMP(option->options[option->userSetChoice],"Point")==0) {
\r
486 ((OsdWin*)Osd::getInstance())->setFilterType(D3DTEXF_POINT);
\r
487 } else if (STRCASECMP(option->options[option->userSetChoice],"Linear")==0) {
\r
488 ((OsdWin*)Osd::getInstance())->setFilterType(D3DTEXF_LINEAR);
\r
493 if (STRCASECMP(option->options[option->userSetChoice],"NoMix")==0) {
\r
494 vmrdeinterlacing=0;
\r
495 } else if (STRCASECMP(option->options[option->userSetChoice],"None")==0) {
\r
496 vmrdeinterlacing=1;
\r
497 } else if (STRCASECMP(option->options[option->userSetChoice],"Best")==0) {
\r
498 vmrdeinterlacing=2;
\r
499 } else if (STRCASECMP(option->options[option->userSetChoice],"Bob")==0) {
\r
500 vmrdeinterlacing=3;
\r
501 } else if (STRCASECMP(option->options[option->userSetChoice],"Weave")==0) {
\r
502 vmrdeinterlacing=4;
\r
506 if (STRCASECMP(option->options[option->userSetChoice],"VMR9")==0) {
\r
507 currentpresenter=VMR9;
\r
508 } else if (STRCASECMP(option->options[option->userSetChoice],"EVR")==0) {
\r
509 currentpresenter=EVR;
\r
513 if (STRCASECMP(option->options[option->userSetChoice],"Yes")==0) {
\r
514 videoH264dtsfix=true;
\r
516 videoH264dtsfix=false;
\r
520 if (STRCASECMP(option->options[option->userSetChoice],"Yes")==0) {
\r
521 videompeg2dtsfix=true;
\r
523 videompeg2dtsfix=false;
\r
531 bool VideoWin::saveOptionstoServer()
\r
533 if (videofilterselected!=-1) {
\r
534 VDR::getInstance()->configSave("DirectShow",
\r
535 "VideoFilter",videofilterlist[videofilterselected].displayname);
\r
536 VDR::getInstance()->configSave("DirectShow",
\r
537 "VideoH264Filter",videoH264filterlist[videoH264filterselected].displayname);
\r
542 /*Option(UINT id, const char* displayText, const char* configSection, const char* configKey, UINT optionType,
\r
543 UINT numChoices, UINT defaultChoice, UINT startInt,
\r
544 const char * const * options, const char * const * optionkeys = NULL, AbstractOption* handler=NULL);*/
\r
546 bool VideoWin::addOptionsToPanes(int panenumber,Options *options,WOptionPane* pane)
\r
548 if (!Video::addOptionsToPanes(panenumber,options,pane)) return false;
\r
552 if (panenumber == 2)
\r
554 DWORD scalingcaps=((OsdWin*)Osd::getInstance())->getFilterCaps();
\r
555 char **scalingopts=new char *[3];
\r
557 scalingopts[i]=new char[strlen("None")+1];
\r
558 strcpy(scalingopts[i],"None");
\r
560 if ((scalingcaps & D3DPTFILTERCAPS_MINFPOINT)!=0
\r
561 && (scalingcaps & D3DPTFILTERCAPS_MAGFPOINT)!=0) {
\r
562 scalingopts[i]=new char[strlen("Point")+1];
\r
563 strcpy(scalingopts[i],"Point");
\r
566 if ((scalingcaps & D3DPTFILTERCAPS_MINFLINEAR)!=0
\r
567 && (scalingcaps & D3DPTFILTERCAPS_MAGFLINEAR)!=0) {
\r
568 scalingopts[i]=new char[strlen("Linear")+1];
\r
569 strcpy(scalingopts[i],"Linear");
\r
572 option = new Option(1 ,tr("Video Stretching Filter"), "DirectGraphics", "StretchFiltering", Option::TYPE_TEXT, i, (i-1), 0, scalingopts,NULL,true, this);
\r
573 options->push_back(option);
\r
574 pane->addOptionLine(option);
\r
575 static const char* deintopts[]={"NoMix","None","Best","Bob","Weave"};
\r
576 option = new Option(2,tr("VMR9 Deinterlacing Mode"), "DirectShow","VMR9DeinterlacingMode",Option::TYPE_TEXT,5,2,0,deintopts,NULL,false,this);
\r
577 options->push_back(option);
\r
578 pane->addOptionLine(option);
\r
580 if (((OsdWin*)Osd::getInstance())->IsEvrSupported())
\r
582 static const char* presenteropts[]={"EVR","VMR9"};
\r
583 option = new Option(3,tr("Video Presenter Filter"),"DirectShow", "VideoPresenter",Option::TYPE_TEXT,2,
\r
584 (currentpresenter==EVR)?0:1,0,presenteropts,NULL,false,this);
\r
586 static const char* presenteropts[]={"VMR9"};
\r
587 option = new Option(3,tr("Video Presenter Filter"),"DirectShow", "VideoPresenter",Option::TYPE_TEXT,1,0,0,presenteropts,NULL,false,this);
\r
589 options->push_back(option);
\r
590 pane->addOptionLine(option);
\r
592 static const char* yesnoopts[]={"Yes","No"};
\r
593 option = new Option(4,tr("Video H264 fix dts time"), "DirectShow","videoH264dtsfix",Option::TYPE_TEXT,2,1,0,yesnoopts,NULL,false,this);
\r
594 options->push_back(option);
\r
595 pane->addOptionLine(option);
\r
597 option = new Option(5,tr("Video Mpeg2 fix dts time"), "DirectShow","videompeg2dtsfix",Option::TYPE_TEXT,2,1,0,yesnoopts,NULL,false,this);
\r
598 options->push_back(option);
\r
599 pane->addOptionLine(option);
\r
608 IBaseFilter *VideoWin::getVideoFilter()
\r
610 IBaseFilter *curfilter= NULL;
\r
611 if (videofilterselected == -1)
\r
614 for (i = 0;i <videofilterlist.size();i++)
\r
617 if (videofilterlist[i].vmr9tested == true)
\r
619 if (videofilterlist[i].vmr9 == true)
\r
621 videofilterselected = i;
\r
631 IMoniker * moni=NULL;
\r
632 IBindCtx *bindctx=NULL;
\r
633 if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
\r
634 LPCOLESTR name=(LPCOLESTR)new WCHAR[strlen(videofilterlist[i].displayname)+1];
\r
635 mbstowcs((wchar_t*)name,videofilterlist[i].displayname,strlen(videofilterlist[i].displayname)+1);
\r
639 if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
\r
641 if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
\r
643 IAMDecoderCaps* desccaps=NULL;
\r
644 if (curfilter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK)
\r
647 desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps);
\r
648 if (caps == DECODER_CAP_SUPPORTED)
\r
650 videofilterlist[i].vmr9tested = true;
\r
651 videofilterlist[i].vmr9 = true;
\r
652 videofilterselected = i;
\r
656 videofilterlist[i].vmr9tested = true;
\r
657 videofilterlist[i].vmr9 = false;
\r
659 curfilter->Release();
\r
663 desccaps->Release();
\r
668 bindctx->Release();
\r
670 if (videofilterlist[i].vmr9) break;
\r
673 if (curfilter != NULL)
\r
675 VDR *vdr=VDR::getInstance();
\r
678 vdr->configSave("DirectShow","VideoFilter",
\r
679 videofilterlist[videofilterselected].displayname);
\r
686 IBindCtx *bindctx=NULL;
\r
687 if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
\r
688 IMoniker * moni=NULL;
\r
689 LPCOLESTR name=new WCHAR[strlen(videofilterlist[videofilterselected].displayname)+1];
\r
690 mbstowcs((wchar_t*)name,videofilterlist[videofilterselected].displayname,
\r
691 strlen(videofilterlist[videofilterselected].displayname)+1);
\r
693 if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
\r
695 if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
\r
697 IAMDecoderCaps* desccaps=NULL;
\r
698 if (curfilter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK)
\r
701 desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps);
\r
702 if (caps == DECODER_CAP_SUPPORTED)
\r
704 videofilterlist[videofilterselected].vmr9tested = true;
\r
705 videofilterlist[videofilterselected].vmr9 = true;
\r
709 videofilterlist[videofilterselected].vmr9tested = true;
\r
710 videofilterlist[videofilterselected].vmr9 = false;
\r
711 Log::getInstance()->log("VideoWin", Log::WARN ,"Filter does not support VMR9, but is selected, manual selection!");
\r
716 bindctx->Release();
\r
721 bindctx->Release();
\r
729 IBaseFilter *VideoWin::getVideoH264Filter()
\r
731 IBaseFilter *curfilter= NULL;
\r
732 if (videoH264filterselected == -1)
\r
735 for (i = 0;i <videoH264filterlist.size();i++)
\r
738 if (videoH264filterlist[i].vmr9tested == true)
\r
740 if (videoH264filterlist[i].vmr9 == true)
\r
742 videoH264filterselected = i;
\r
752 IMoniker * moni=NULL;
\r
753 IBindCtx *bindctx=NULL;
\r
754 if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
\r
755 LPCOLESTR name=(LPCOLESTR)new WCHAR[strlen(videoH264filterlist[i].displayname)+1];
\r
756 mbstowcs((wchar_t*)name,videoH264filterlist[i].displayname,strlen(videoH264filterlist[i].displayname)+1);
\r
758 Log::getInstance()->log("VideoWin", Log::DEBUG ,"Creating filter: %s",videoH264filterlist[i].friendlyname);
\r
762 if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
\r
764 if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
\r
766 IAMDecoderCaps* desccaps=NULL;
\r
767 if (curfilter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK)
\r
770 desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps);
\r
771 if (caps == DECODER_CAP_SUPPORTED)
\r
773 videoH264filterlist[i].vmr9tested = true;
\r
774 videoH264filterlist[i].vmr9 = true;
\r
775 videoH264filterselected = i;
\r
779 videoH264filterlist[i].vmr9tested = true;
\r
780 videoH264filterlist[i].vmr9 = false;
\r
782 curfilter->Release();
\r
786 desccaps->Release();
\r
791 bindctx->Release();
\r
793 if (videoH264filterlist[i].vmr9) break;
\r
796 if (curfilter != NULL)
\r
798 VDR *vdr=VDR::getInstance();
\r
801 vdr->configSave("DirectShow","VideoH264Filter",
\r
802 videoH264filterlist[videoH264filterselected].displayname);
\r
809 IBindCtx *bindctx=NULL;
\r
810 if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
\r
811 IMoniker * moni=NULL;
\r
812 LPCOLESTR name=new WCHAR[strlen(videoH264filterlist[videoH264filterselected].displayname)+1];
\r
813 mbstowcs((wchar_t*)name,videoH264filterlist[videoH264filterselected].displayname,
\r
814 strlen(videoH264filterlist[videoH264filterselected].displayname)+1);
\r
816 Log::getInstance()->log("VideoWin", Log::DEBUG ,"Creating filter: %s",videoH264filterlist[videoH264filterselected].friendlyname);
\r
817 if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
\r
819 if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
\r
821 IAMDecoderCaps* desccaps=NULL;
\r
822 if (curfilter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK)
\r
825 desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps);
\r
826 if (caps == DECODER_CAP_SUPPORTED)
\r
828 videoH264filterlist[videoH264filterselected].vmr9tested = true;
\r
829 videoH264filterlist[videoH264filterselected].vmr9 = true;
\r
833 videoH264filterlist[videoH264filterselected].vmr9tested = true;
\r
834 videoH264filterlist[videoH264filterselected].vmr9 = false;
\r
835 Log::getInstance()->log("VideoWin", Log::WARN ,"Filter does not support VMR9, but is selected, manual selection!");
\r
840 bindctx->Release();
\r
845 bindctx->Release();
\r
854 #ifdef DS_DEBUG // This stuff would not included in vomp due to lincemse restrcitions
\r
855 #include "dshelper.h"
\r
860 int VideoWin::play()
\r
862 if (!initted) return 0;
\r
866 bool VideoWin::addOptionPagesToWTB(WTabBar *wtb)
\r
868 Boxx *box=new WWinVideoFilter();
\r
869 wtb->addTab(tr("Video Filter"), box);
\r
870 box=new WWinVideoH264Filter();
\r
871 wtb->addTab(tr("H264 Filter"), box);
\r
875 const VideoFilterDescList *VideoWin::getVideoFilterList(int &selected)
\r
877 selected=videofilterselected;
\r
878 return &videofilterlist;
\r
881 const VideoFilterDescList *VideoWin::getVideoH264FilterList(int &selected)
\r
883 selected=videoH264filterselected;
\r
884 return &videoH264filterlist;
\r
887 bool VideoWin::selectVideoFilter(int filter)
\r
889 IBindCtx *bindctx=NULL;
\r
890 if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
\r
891 IMoniker * moni=NULL;
\r
892 LPCOLESTR name=new WCHAR[strlen(videofilterlist[filter].displayname)+1];
\r
893 mbstowcs((wchar_t*)name,videofilterlist[filter].displayname,
\r
894 strlen(videofilterlist[filter].displayname)+1);
\r
896 bool success=false;
\r
897 if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
\r
899 IBaseFilter* curfilter=NULL;
\r
900 if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
\r
902 IAMDecoderCaps* desccaps=NULL;
\r
903 if (curfilter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK)
\r
906 HRESULT hres=desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps);
\r
907 if (caps == DECODER_CAP_SUPPORTED)
\r
909 videofilterlist[filter].vmr9tested = true;
\r
910 videofilterlist[filter].vmr9 = true;
\r
915 videofilterlist[filter].vmr9tested = true;
\r
916 videofilterlist[filter].vmr9 = false;
\r
919 desccaps->Release();
\r
921 videofilterlist[filter].vmr9tested = true;
\r
922 videofilterlist[filter].vmr9 = false;
\r
926 curfilter->Release();
\r
931 bindctx->Release();
\r
933 if (success || true)
\r
935 videofilterselected=filter;
\r
944 bool VideoWin::selectVideoH264Filter(int filter)
\r
946 IBindCtx *bindctx=NULL;
\r
947 if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
\r
948 IMoniker * moni=NULL;
\r
949 LPCOLESTR name=new WCHAR[strlen(videoH264filterlist[filter].displayname)+1];
\r
950 mbstowcs((wchar_t*)name,videoH264filterlist[filter].displayname,
\r
951 strlen(videoH264filterlist[filter].displayname)+1);
\r
953 bool success=false;
\r
954 if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
\r
956 IBaseFilter* curfilter=NULL;
\r
957 if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
\r
959 IAMDecoderCaps* desccaps=NULL;
\r
960 if (curfilter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK)
\r
963 HRESULT hres=desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps);
\r
964 if (caps == DECODER_CAP_SUPPORTED)
\r
966 videoH264filterlist[filter].vmr9tested = true;
\r
967 videoH264filterlist[filter].vmr9 = true;
\r
972 videoH264filterlist[filter].vmr9tested = true;
\r
973 videoH264filterlist[filter].vmr9 = false;
\r
976 desccaps->Release();
\r
978 videoH264filterlist[filter].vmr9tested = true;
\r
979 videoH264filterlist[filter].vmr9 = false;
\r
983 curfilter->Release();
\r
988 bindctx->Release();
\r
990 if (success || true)
\r
992 videoH264filterselected=filter;
\r
1001 int VideoWin::dsInitVideoFilter()
\r
1006 //We alloc the vmr9 as next step
\r
1007 if (currentpresenter==VMR9)
\r
1009 Log::getInstance()->log("VideoWin", Log::INFO ,"VMR9 Videopresenter selected!");
\r
1010 if (hres=CoCreateInstance(CLSID_VideoMixingRenderer9,0,
\r
1011 CLSCTX_INPROC_SERVER,IID_IBaseFilter,(void**) &dsrenderer)!=S_OK)
\r
1013 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed creating VMR9 renderer!");
\r
1014 ReleaseMutex(filtermutex);
\r
1018 if (hres=dsgraphbuilder->AddFilter(dsrenderer,L"VMR9")!=S_OK)
\r
1020 ReleaseMutex(filtermutex);
\r
1022 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed adding VMR9 renderer!");
\r
1025 IVMRFilterConfig9* vmrfilconfig;
\r
1026 if (dsrenderer->QueryInterface(IID_IVMRFilterConfig9,(void**)&vmrfilconfig)!=S_OK)
\r
1028 ReleaseMutex(filtermutex);
\r
1030 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Filterconfig interface!");
\r
1033 if (vmrdeinterlacing!=0) vmrfilconfig->SetNumberOfStreams(1);//Enter Mixing Mode
\r
1034 vmrfilconfig->SetRenderingMode(VMR9Mode_Renderless);
\r
1035 vmrfilconfig->Release();
\r
1036 if (dsrenderer->QueryInterface(IID_IVMRSurfaceAllocatorNotify9,
\r
1037 (void**)& dsvmrsurfnotify) != S_OK)
\r
1039 ReleaseMutex(filtermutex);
\r
1041 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Surface Allocator interface!");
\r
1044 allocatorvmr=new DsAllocator();
\r
1045 dsvmrsurfnotify->AdviseSurfaceAllocator(NULL,allocatorvmr);
\r
1046 allocatorvmr->AdviseNotify(dsvmrsurfnotify);
\r
1048 IVMRDeinterlaceControl9* deintctrl;
\r
1049 if (dsrenderer->QueryInterface(IID_IVMRDeinterlaceControl9,(void**)&deintctrl)!=S_OK)
\r
1051 ReleaseMutex(filtermutex);
\r
1053 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Deinterlace control!");
\r
1057 switch (vmrdeinterlacing)
\r
1059 case 1: //No Deinterlasing
\r
1060 deintctrl->SetDeinterlaceMode(0xFFFFFFFF,(LPGUID)&GUID_NULL);//Turn Off
\r
1063 deintctrl->SetDeinterlacePrefs(DeinterlacePref_NextBest);//Choose Next Best
\r
1066 deintctrl->SetDeinterlacePrefs(DeinterlacePref_BOB);//Choose NBob
\r
1069 deintctrl->SetDeinterlacePrefs(DeinterlacePref_Weave);//Choose Weave
\r
1072 deintctrl->Release();
\r
1073 /*VMR 9 stuff end */
\r
1075 else if (currentpresenter==EVR)
\r
1077 Log::getInstance()->log("VideoWin", Log::INFO ,"EVR Videopresenter selected!");
\r
1078 if (hres=CoCreateInstance(CLSID_EnhancedVideoRenderer,0,
\r
1079 CLSCTX_INPROC_SERVER,IID_IBaseFilter,(void**) &dsrenderer)!=S_OK)
\r
1081 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed creating EVR renderer!");
\r
1082 ReleaseMutex(filtermutex);
\r
1086 if (hres=dsgraphbuilder->AddFilter(dsrenderer,L"EVR")!=S_OK)
\r
1088 ReleaseMutex(filtermutex);
\r
1090 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed adding EVR renderer!");
\r
1095 IMFGetService *evr_services;
\r
1096 if (dsrenderer->QueryInterface(IID_IMFGetService,(void**)&evr_services)!=S_OK)
\r
1098 ReleaseMutex(filtermutex);
\r
1100 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting EVR IMFGetServices interface!");
\r
1104 IMFVideoDisplayControl* mfvideodisplaycontrol;
\r
1105 if (evr_services->GetService(MR_VIDEO_RENDER_SERVICE,IID_IMFVideoDisplayControl,(void**)&mfvideodisplaycontrol)!=S_OK)
\r
1107 ReleaseMutex(filtermutex);
\r
1109 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting EVR IMFVideoDisplayControl interface!");
\r
1113 evr_services->Release();
\r
1114 mfvideodisplaycontrol->SetVideoWindow(((OsdWin*) Osd::getInstance())->getWindow());
\r
1116 //GetClientRect(((OsdWin*) Osd::getInstance())->getWindow(), &client);
\r
1117 //mfvideodisplaycontrol->SetVideoPosition(NULL,&client);
\r
1119 mfvideodisplaycontrol->Release();
\r
1122 /// if (vmrdeinterlacing!=0) vmrfilconfig->SetNumberOfStreams(1);//Enter Mixing Mode //always the case for evr!
\r
1124 IMFVideoRenderer *mfvideorenderer;
\r
1125 if (dsrenderer->QueryInterface(IID_IMFVideoRenderer,(void**)&mfvideorenderer)!=S_OK)
\r
1127 ReleaseMutex(filtermutex);
\r
1129 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting EVR IMFVideoRenderer interface!");
\r
1133 allocatorvmr=new DsAllocator();
\r
1134 HRESULT hres=mfvideorenderer->InitializeRenderer(NULL,allocatorvmr);
\r
1136 mfvideorenderer->Release();
\r
1137 //How should I do this in EVR?
\r
1138 /* IVMRDeinterlaceControl9* deintctrl;
\r
1139 if (dsrenderer->QueryInterface(IID_IVMRDeinterlaceControl9,(void**)&deintctrl)!=S_OK)
\r
1141 ReleaseMutex(filtermutex);
\r
1143 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Deinterlace control!");
\r
1147 switch (vmrdeinterlacing)
\r
1149 case 1: //No Deinterlasing
\r
1150 deintctrl->SetDeinterlaceMode(0xFFFFFFFF,(LPGUID)&GUID_NULL);//Turn Off
\r
1153 deintctrl->SetDeinterlacePrefs(DeinterlacePref_NextBest);//Choose Next Best
\r
1156 deintctrl->SetDeinterlacePrefs(DeinterlacePref_BOB);//Choose NBob
\r
1159 deintctrl->SetDeinterlacePrefs(DeinterlacePref_Weave);//Choose Weave
\r
1162 deintctrl->Release();*/
\r
1163 /*EVR stuff end */
\r
1165 Log::getInstance()->log("VideoWin", Log::ERR ,"No videopresenter selected! Please post on the forum!");
\r
1168 IFilterGraph2*fg2=NULL;
\r
1169 if (dsgraphbuilder->QueryInterface(IID_IFilterGraph2,(void**)&fg2)!= S_OK)
\r
1171 Log::getInstance()->log("VideoWin", Log::WARN , "Failed querying for FilterGraph2 Interface!");
\r
1172 ReleaseMutex(filtermutex);
\r
1176 /*#ifndef NEW_DS_MECHANISMENS
\r
1178 if (hres=fg2->RenderEx((IPin*)sourcefilter->GetVideoPin()/*video*,
\r
1179 AM_RENDEREX_RENDERTOEXISTINGRENDERERS,NULL) != S_OK)
\r
1181 Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering Video!");
\r
1183 ReleaseMutex(filtermutex);
\r
1189 IBaseFilter*videofilter;
\r
1192 Log::getInstance()->log("VideoWin", Log::DEBUG ,"Entering h264 playback...");
\r
1193 videofilter=getVideoH264Filter();
\r
1197 Log::getInstance()->log("VideoWin", Log::DEBUG ,"Entering MPEG2 playback...");
\r
1198 videofilter=getVideoFilter();
\r
1200 if (hres=dsgraphbuilder->AddFilter(videofilter,NULL) != S_OK)
\r
1202 Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Video Filter!");
\r
1203 ReleaseMutex(filtermutex);
\r
1207 IEnumPins *pinenum=NULL;
\r
1210 mptype_video_detail vid_details;
\r
1211 Demuxer* demux=Demuxer::getInstance();
\r
1212 vid_details.width=demux->getHorizontalSize();
\r
1213 vid_details.height=demux->getVerticalSize();
\r
1217 if (vid_details.width!=0 && vid_details.height!=0)
\r
1219 sourcefilter->GetVideoPin()->SetPinMode(MPTYPE_VIDEO_H264,&vid_details);
\r
1223 sourcefilter->GetVideoPin()->SetPinMode(MPTYPE_VIDEO_H264,NULL);
\r
1229 if (vid_details.width!=0 && vid_details.height!=0)
\r
1231 sourcefilter->GetVideoPin()->SetPinMode(MPTYPE_VIDEO_MPEG2,&vid_details);
\r
1235 sourcefilter->GetVideoPin()->SetPinMode(MPTYPE_VIDEO_MPEG2,NULL);
\r
1238 if (videofilter->EnumPins(&pinenum) == S_OK)
\r
1240 IPin *current=NULL;
\r
1242 bool firststep=false;
\r
1244 while (pinenum->Next(1,¤t,&fetch)==S_OK)
\r
1246 PIN_DIRECTION dir;
\r
1247 if (current->QueryDirection(&dir)==S_OK)
\r
1249 if (dir == PINDIR_INPUT)
\r
1251 if (sourcefilter->GetVideoPin()->Connect(current,NULL)==S_OK)
\r
1253 current->Release();
\r
1259 current->Release();
\r
1261 if (firststep==false)
\r
1263 Log::getInstance()->log("VideoWin", Log::WARN , "Video Filter has no suitable input!");
\r
1264 videofilter->Release();
\r
1265 ReleaseMutex(filtermutex);
\r
1269 bool secondstep=false;
\r
1271 while (pinenum->Next(1,¤t,&fetch)==S_OK)
\r
1273 PIN_DIRECTION dir;
\r
1274 if (current->QueryDirection(&dir)==S_OK)
\r
1276 if (dir == PINDIR_OUTPUT)
\r
1279 if (fg2->RenderEx((IPin*)current/*video*/,
\r
1280 AM_RENDEREX_RENDERTOEXISTINGRENDERERS,NULL) ==S_OK)
\r
1282 current->Release();
\r
1288 current->Release();
\r
1290 if (secondstep==false)
\r
1292 Log::getInstance()->log("VideoWin", Log::WARN , "Video Filter has no suitable output!");
\r
1293 videofilter->Release();
\r
1294 ReleaseMutex(filtermutex);
\r
1299 videofilter->Release();
\r
1300 pinenum->Release();
\r
1313 int VideoWin::setAudioStreamType(UCHAR type)
\r
1316 if (!initted) return 0;
\r
1320 int VideoWin::dsplay()
\r
1322 if (!initted) return 0;
\r
1325 //Build filter graph
\r
1327 //So this is the real code, this prevents the feeder from calling noexisting objects!
\r
1328 WaitForSingleObject(filtermutex,INFINITE);
\r
1329 if (hres=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,
\r
1330 IID_IGraphBuilder,(void**)&dsgraphbuilder) != S_OK)
\r
1332 ReleaseMutex(filtermutex);
\r
1336 AddToRot(dsgraphbuilder,&graphidentifier);
\r
1339 firstsynched=false;
\r
1340 if (aud_type==Audio::MP3) {
\r
1341 lastaudiomode=MPTYPE_MPEG_AUDIO_LAYER3;
\r
1343 lastaudiomode=MPTYPE_MPEG_AUDIO;
\r
1345 //lastaudiomode=MPTYPE_AC3;
\r
1346 sourcefilter=new DsSourceFilter(); //Creating our Source filter for pushing Data
\r
1348 if (hres=dsgraphbuilder->AddFilter(sourcefilter,L"Vomp Win Source Filter") != S_OK)
\r
1350 Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Vomp Source Filter!");
\r
1351 ReleaseMutex(filtermutex);
\r
1355 sourcefilter->GetAudioPin()->SetPinMode(lastaudiomode);
\r
1356 /*if (hres=dsgraphbuilder->Render((IPin*)sourcefilter->GetAudioPin()/*audio*)!=S_OK)
\r
1358 Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering audio!");
\r
1359 ReleaseMutex(filtermutex);
\r
1363 if (((AudioWin*)Audio::getInstance())->dsInitAudioFilter(dsgraphbuilder)==0)
\r
1365 Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering audio!");
\r
1366 ReleaseMutex(filtermutex);
\r
1372 if (dsInitVideoFilter()==0)
\r
1377 if (hres=CoCreateInstance(CLSID_SystemClock,NULL,CLSCTX_INPROC_SERVER,
\r
1378 IID_IReferenceClock,(void**)&dsrefclock)!=S_OK)
\r
1382 dsgraphbuilder->QueryInterface(IID_IMediaFilter,(void **) &dsmediafilter);
\r
1383 HRESULT hresdeb = dsmediafilter->SetSyncSource(dsrefclock);
\r
1385 dsgraphbuilder->QueryInterface(IID_IMediaControl,(void **) &dsmediacontrol);
\r
1386 dsgraphbuilder->QueryInterface(IID_IBasicAudio,(void **) &dsbasicaudio);
\r
1387 if (dsbasicaudio)
\r
1388 dsbasicaudio->put_Volume(audiovolume);
\r
1390 //MILLISLEEP(100);
\r
1392 hresdeb=dsmediacontrol->Run();
\r
1393 iframemode=false;//exit iframe mode
\r
1394 ReleaseMutex(filtermutex);
\r
1398 int VideoWin::EnterIframePlayback()
\r
1400 if (!initted) return 0;
\r
1402 //So this is the real code, this prevents the feeder from calling noexisting objects!
\r
1403 WaitForSingleObject(filtermutex,INFINITE);
\r
1404 iframemode=true;//enter iframe mode
\r
1405 //Build filter graph
\r
1407 if (hres=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,
\r
1408 IID_IGraphBuilder,(void**)&dsgraphbuilder)!=S_OK) {
\r
1409 ReleaseMutex(filtermutex);
\r
1413 AddToRot(dsgraphbuilder,&graphidentifier);
\r
1416 //firstsynched=false;
\r
1417 sourcefilter=new DsSourceFilter(); //Creating our Source filter for pushing Data
\r
1419 if (hres=dsgraphbuilder->AddFilter(sourcefilter,L"Vomp Win Source Filter")!=S_OK) {
\r
1420 Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Vomp Source Filter!");
\r
1421 ReleaseMutex(filtermutex);
\r
1427 dsInitVideoFilter();
\r
1430 /* if (hres=CoCreateInstance(CLSID_SystemClock,NULL,CLSCTX_INPROC_SERVER,
\r
1431 IID_IReferenceClock,(void**)&dsrefclock)!=S_OK) {
\r
1435 dsgraphbuilder->QueryInterface(IID_IMediaFilter,(void **) &dsmediafilter);
\r
1436 dsmediafilter->SetSyncSource(/*dsrefclock*/NULL); //Run as fast as you can!
\r
1438 dsgraphbuilder->QueryInterface(IID_IMediaControl,(void **) &dsmediacontrol);
\r
1439 dsgraphbuilder->QueryInterface(IID_IBasicAudio,(void **) &dsbasicaudio);
\r
1443 dsmediacontrol->Run();
\r
1444 ReleaseMutex(filtermutex);
\r
1449 int VideoWin::dsstop()
\r
1451 if (!initted) return 0;
\r
1459 int VideoWin::stop()
\r
1461 if (!initted) return 0;
\r
1467 int VideoWin::reset()
\r
1469 if (!initted) return 0;
\r
1475 int VideoWin::dsreset()
\r
1477 if (!initted) return 0;
\r
1480 iframemode=false;//exit iframe mode
\r
1486 int VideoWin::dspause()
\r
1488 if (!initted) return 0;
\r
1489 WaitForSingleObject(filtermutex,INFINITE);
\r
1490 if (dsmediacontrol) dsmediacontrol->Pause();
\r
1491 ReleaseMutex(filtermutex);
\r
1495 int VideoWin::pause()
\r
1497 if (!initted) return 0;
\r
1502 int VideoWin::unPause() // FIXME get rid - same as play!!
\r
1503 {//No on windows this is not the same, I don't get rid of!
\r
1504 if (!initted) return 0;
\r
1508 int VideoWin::dsunPause() // FIXME get rid - same as play!!
\r
1509 {//No on windows this is not the same, I don't get rid of!
\r
1510 if (!initted) return 0;
\r
1511 WaitForSingleObject(filtermutex,INFINITE);
\r
1512 if (dsmediacontrol) dsmediacontrol->Run();
\r
1513 ReleaseMutex(filtermutex);
\r
1518 int VideoWin::fastForward()
\r
1520 if (!initted) return 0;
\r
1525 int VideoWin::unFastForward()
\r
1527 if (!initted) return 0;
\r
1532 int VideoWin::attachFrameBuffer()
\r
1534 if (!initted) return 0;
\r
1538 int VideoWin::blank(void)
\r
1540 ((OsdWin*)Osd::getInstance())->Blank();
\r
1544 ULLONG VideoWin::getCurrentTimestamp()
\r
1546 REFERENCE_TIME startoffset;
\r
1547 REFERENCE_TIME ncr_time;
\r
1548 if (iframemode) return 0; //Not in iframe mode!
\r
1549 if (!dsrefclock || !sourcefilter) return 0;
\r
1550 FILTER_STATE state;
\r
1551 sourcefilter->GetState(10,&state);
\r
1553 if (state==State_Running) dsrefclock->GetTime(&cr_time);
\r
1555 startoffset=sourcefilter->getStartOffset();
\r
1556 if (startoffset==0) return 0;
\r
1557 ncr_time-=startoffset;
\r
1558 ncr_time-=lastreftimeRT;
\r
1559 /* ULLONG result=frameNumberToTimecode(
\r
1560 VDR::getInstance()->frameNumberFromPosition(lastreftimeBYTE));*/
\r
1561 long long result=lastreftimePTS;
\r
1562 result+=(ULLONG)(ncr_time/10000LL*90LL);
\r
1563 if (result<0) result=(1LL << 33)-result;
\r
1570 ULONG VideoWin::timecodeToFrameNumber(ULLONG timecode)
\r
1572 if (format == PAL) return (ULONG)(((double)timecode / (double)90000) * (double)25);
\r
1573 else return (ULONG)(((double)timecode / (double)90000) * (double)30);
\r
1576 ULLONG VideoWin::frameNumberToTimecode(ULONG framenumber)
\r
1578 if (format == PAL) return (ULLONG)(((double)framenumber * (double)90000) / (double)25);
\r
1579 else return (ULLONG)(((double)framenumber * (double)90000) / (double)30);
\r
1582 void VideoWin::CleanupDS()
\r
1584 WaitForSingleObject(filtermutex,INFINITE);
\r
1586 if (dsmediacontrol)dsmediacontrol->Stop();
\r
1587 if (cur_audio_media_sample) {
\r
1588 cur_audio_media_sample->Release();
\r
1589 cur_audio_media_sample=NULL;
\r
1591 if (cur_video_media_sample) {
\r
1592 cur_video_media_sample->Release();
\r
1593 cur_video_media_sample=NULL;
\r
1595 if (dsbasicaudio) {
\r
1596 dsbasicaudio->Release();
\r
1597 dsbasicaudio=NULL;
\r
1599 if (dsvmrsurfnotify) {
\r
1600 dsvmrsurfnotify->Release();
\r
1601 dsvmrsurfnotify=NULL;
\r
1604 dsrenderer->Release();
\r
1608 if (allocatorvmr) {
\r
1609 allocatorvmr->Release();
\r
1610 allocatorvmr=NULL;
\r
1614 dsrefclock->Release();
\r
1617 if (dsmediafilter) {
\r
1618 dsmediafilter->Release();
\r
1619 dsmediafilter=NULL;
\r
1624 if (dsmediacontrol) {
\r
1625 dsmediacontrol->Stop();
\r
1626 dsmediacontrol->Release();
\r
1627 dsmediacontrol=NULL;
\r
1629 if (dsgraphbuilder){
\r
1631 RemoveFromRot(graphidentifier);
\r
1633 dsgraphbuilder->Release();
\r
1634 dsgraphbuilder=NULL;
\r
1636 sourcefilter=NULL; //The Graph Builder destroys our SourceFilter
\r
1638 ReleaseMutex(filtermutex);
\r
1642 void VideoWin::PrepareMediaSample(const MediaPacketList& mplist,
\r
1645 mediapacket = mplist.front();
\r
1648 UINT VideoWin::DeliverMediaSample(UCHAR* buffer, UINT *samplepos)
\r
1650 DeliverMediaPacket(mediapacket, buffer, samplepos);
\r
1651 if (*samplepos == mediapacket.length) {
\r
1658 UINT VideoWin::DeliverMediaPacket(MediaPacket packet,
\r
1659 const UCHAR* buffer,
\r
1663 /*First Check, if we have an audio sample*/
\r
1664 if (!isdsinited()) return 0;
\r
1665 if (packet.type == MPTYPE_VIDEO_H264)
\r
1676 *samplepos+=packet.length;
\r
1677 MILLISLEEP(0); //yet not implemented//bad idea
\r
1678 return packet.length;
\r
1680 /*First Check, if we have an audio sample*/
\r
1684 return 0; //Not in iframe mode!
\r
1686 IMediaSample* ms=NULL;
\r
1687 REFERENCE_TIME reftime1=0;
\r
1688 REFERENCE_TIME reftime2=0;
\r
1690 UINT headerstrip=0;
\r
1691 if (packet.disconti) {
\r
1692 firstsynched=false;
\r
1693 DeliverVideoMediaSample();
\r
1698 /*Inspect PES-Header */
\r
1700 if (*samplepos==0) {//stripheader
\r
1701 headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/;
\r
1702 *samplepos+=headerstrip;
\r
1703 if ( packet.synched ) {
\r
1704 DeliverVideoMediaSample();//write out old data
\r
1705 /* if (packet.presentation_time<0) { //Preroll?
\r
1706 *samplepos=packet.length;//if we have not processed at least one
\r
1707 return packet.length;//synched packet ignore it!
\r
1710 reftime1=packet.presentation_time;
\r
1711 reftime2=reftime1+1;
\r
1712 firstsynched=true;
\r
1714 if (!firstsynched) {//
\r
1715 *samplepos=packet.length;//if we have not processed at least one
\r
1716 return packet.length;//synched packet ignore it!
\r
1725 if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
\r
1727 //MessageBox(0,"da isser","hei",0);
\r
1731 ms_pos=ms->GetActualDataLength();
\r
1732 ms_length=ms->GetSize();
\r
1733 haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);
\r
1734 if ((ms_length-ms_pos)<1 ) {
\r
1735 DeliverVideoMediaSample(); //we are full!
\r
1736 if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
\r
1738 //MessageBox(0,"da isser","hei",0);
\r
1742 ms_pos=ms->GetActualDataLength();
\r
1743 ms_length=ms->GetSize();
\r
1744 haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);
\r
1746 ms->GetPointer(&ms_buf);
\r
1749 if (ms_pos==0) {//will only be changed on first packet
\r
1750 if (packet.disconti) {
\r
1751 ms->SetDiscontinuity(TRUE);
\r
1753 ms->SetDiscontinuity(FALSE);
\r
1755 if (packet.synched) {
\r
1756 ms->SetSyncPoint(TRUE);
\r
1757 ms->SetTime(&reftime1,&reftime2);
\r
1758 //Log::getInstance()->log("VideoWin", Log::DEBUG , "Setted videotime to %lld %lld",reftime1,reftime2);
\r
1759 //Log::getInstance()->log("VideoWin", Log::DEBUG , "Packet pts %lld dts %lld",packet.pts,packet.dts);
\r
1760 //ms->SetTime(NULL,NULL);
\r
1761 ms->SetMediaTime(NULL, NULL);
\r
1762 if (reftime1<0) ms->SetPreroll(TRUE);
\r
1763 else ms->SetPreroll(FALSE);
\r
1764 /*Timecode handling*/
\r
1765 lastreftimeRT=reftime1;
\r
1766 lastreftimePTS=packet.pts;
\r
1771 ms->SetSyncPoint(FALSE);
\r
1772 ms->SetTime(NULL,NULL);
\r
1773 ms->SetMediaTime(NULL, NULL);
\r
1774 ms->SetPreroll(FALSE);
\r
1776 // ms->SetSyncPoint(TRUE);
\r
1782 memcpy(ms_buf+ms_pos,buffer+packet.pos_buffer+*samplepos,haveToCopy);
\r
1783 ms->SetActualDataLength(haveToCopy+ms_pos);
\r
1785 *samplepos+=haveToCopy;
\r
1787 return haveToCopy+headerstrip;
\r
1791 *samplepos+=packet.length;
\r
1792 MILLISLEEP(0); //yet not implemented//bad idea
\r
1793 return packet.length;
\r
1797 int VideoWin::getCurrentAudioMediaSample(IMediaSample** ms)
\r
1799 //WaitForSingleObject(filtermutex,INFINITE);
\r
1800 if (!sourcefilter){
\r
1801 // ReleaseMutex(filtermutex);
\r
1804 if (cur_audio_media_sample) {
\r
1805 *ms=cur_audio_media_sample;//already open
\r
1808 if (!sourcefilter->getCurrentAudioMediaSample(ms)) {
\r
1809 // ReleaseMutex(filtermutex);
\r
1811 if (*ms) (*ms)->SetActualDataLength(0);
\r
1812 cur_audio_media_sample=*ms;
\r
1813 //Don't release the mutex before deliver
\r
1817 int VideoWin::getCurrentVideoMediaSample(IMediaSample** ms)
\r
1819 //WaitForSingleObject(filtermutex,INFINITE);
\r
1820 if (!sourcefilter){
\r
1821 // ReleaseMutex(filtermutex);
\r
1824 if (cur_video_media_sample) {
\r
1825 *ms=cur_video_media_sample;//already open
\r
1828 if (!sourcefilter->getCurrentVideoMediaSample(ms)) {
\r
1829 // ReleaseMutex(filtermutex);
\r
1831 if (*ms) (*ms)->SetActualDataLength(0);
\r
1833 cur_video_media_sample=*ms;
\r
1834 //Don't release the mutex before deliver
\r
1838 int VideoWin::DeliverAudioMediaSample(){
\r
1839 if (cur_audio_media_sample) {
\r
1840 sourcefilter->DeliverAudioMediaSample(cur_audio_media_sample);
\r
1841 cur_audio_media_sample=NULL;
\r
1843 //ReleaseMutex(filtermutex);
\r
1847 int VideoWin::DeliverVideoMediaSample(){
\r
1848 if (cur_video_media_sample) {
\r
1849 sourcefilter->DeliverVideoMediaSample(cur_video_media_sample);
\r
1850 cur_video_media_sample=NULL;
\r
1852 //ReleaseMutex(filtermutex);
\r
1856 long long VideoWin::SetStartOffset(long long curreftime, bool *rsync)
\r
1859 if (offsetnotset) {
\r
1860 startoffset=curreftime;//offset is set for audio
\r
1861 offsetnotset=false;
\r
1862 offsetvideonotset=false;
\r
1866 if (offsetvideonotset) {
\r
1867 offsetvideonotset=false;
\r
1870 if ( (curreftime-lastrefvideotime)>10000000LL
\r
1871 || (curreftime-lastrefvideotime)<-10000000LL) {//if pts jumps to big resync
\r
1872 startoffset+=curreftime-lastrefvideotime;
\r
1873 lastrefaudiotime+=curreftime-lastrefvideotime;
\r
1875 offsetaudionotset=true;
\r
1882 lastrefvideotime=curreftime;
\r
1884 return startoffset;
\r
1888 long long VideoWin::SetStartAudioOffset(long long curreftime, bool *rsync)
\r
1891 if (offsetnotset) {
\r
1892 startoffset=curreftime;
\r
1893 offsetnotset=false;
\r
1894 offsetaudionotset=false;
\r
1896 if (offsetaudionotset) {
\r
1897 offsetaudionotset=false;
\r
1900 if ( (curreftime-lastrefaudiotime)>10000000LL
\r
1901 || (curreftime-lastrefaudiotime)<-10000000LL) {//if pts jumps to big resync
\r
1902 startoffset+=curreftime-lastrefaudiotime;
\r
1903 lastrefvideotime+=curreftime-lastrefaudiotime;
\r
1905 offsetvideonotset=true;
\r
1911 lastrefaudiotime=curreftime;
\r
1912 return startoffset;
\r
1915 void VideoWin::ResetTimeOffsets() {
\r
1916 offsetnotset=true; //called from demuxer
\r
1917 offsetvideonotset=true;
\r
1918 offsetaudionotset=true;
\r
1920 lastrefaudiotime=0;
\r
1921 lastrefvideotime=0;
\r
1928 void VideoWin::SetAudioVolume(long volume)
\r
1930 audiovolume=volume;
\r
1931 if (dsbasicaudio) dsbasicaudio->put_Volume(volume);
\r
1934 bool VideoWin::displayIFrame(const UCHAR* buffer, UINT length)
\r
1936 if (!iframemode) EnterIframePlayback();
\r
1937 if (!isdsinited()) return false;
\r
1940 IMediaSample* ms=NULL;
\r
1941 REFERENCE_TIME reftime1=0;
\r
1942 REFERENCE_TIME reftime2=0;
\r
1943 if (!videoon) return;
\r
1944 if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
\r
1950 ms->GetPointer(&ms_buf);
\r
1951 ms_length=ms->GetSize();
\r
1953 /*First Check, if we have an video sample*/
\r
1954 DWORD read_pos = 0, write_pos = 0;
\r
1955 DWORD pattern, packet_length;
\r
1956 DWORD headerstrip=0;
\r
1958 if (length < 4) return ;
\r
1959 //Now we strip the pes header
\r
1960 pattern = (buffer[0] << 16) | (buffer[1] << 8) | (buffer[2]);
\r
1961 while (read_pos + 7 <= length)
\r
1963 pattern = ((pattern << 8) & 0xFFFFFFFF) | buffer[read_pos+3];
\r
1964 if (pattern < 0x000001E0 || pattern > 0x000001EF) {
\r
1970 headerstrip=buffer[read_pos+8]+9/*is this right*/;
\r
1971 packet_length = ((buffer[read_pos+4] << 8) | (buffer[read_pos+5])) + 6;
\r
1972 if (read_pos + packet_length > length)
\r
1973 read_pos = length;
\r
1976 if ( (headerstrip < packet_length) &&
\r
1977 (write_pos+packet_length-headerstrip)>ms_length) {
\r
1979 ms->SetSyncPoint(TRUE);
\r
1980 ms->SetDiscontinuity(TRUE);
\r
1982 } else ms->SetSyncPoint(FALSE);
\r
1983 ms->SetTime(NULL,NULL);
\r
1984 ms->SetMediaTime(NULL, NULL);
\r
1985 ms->SetActualDataLength(write_pos);
\r
1986 DeliverVideoMediaSample();
\r
1988 if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
\r
1993 ms_length=ms->GetSize();
\r
1994 ms->GetPointer(&ms_buf);
\r
1996 if (packet_length>headerstrip) {
\r
1997 memcpy(ms_buf+write_pos, buffer+read_pos+headerstrip, packet_length-headerstrip);
\r
1998 write_pos += packet_length-headerstrip;
\r
2000 read_pos += packet_length;
\r
2002 pattern = (buffer[read_pos] << 16) | (buffer[read_pos+1] << 8)
\r
2003 | (buffer[read_pos+2]);
\r
2008 if (first) {ms->SetSyncPoint(TRUE);
\r
2009 ms->SetDiscontinuity(TRUE);
\r
2011 else ms->SetSyncPoint(FALSE);
\r
2012 ms->SetTime(NULL,NULL);
\r
2013 ms->SetMediaTime(NULL, NULL);
\r
2014 ms->SetActualDataLength(write_pos);
\r
2015 DeliverVideoMediaSample();
\r
2020 // *samplepos+=packet.length;
\r
2021 MILLISLEEP(0); //yet not implemented//bad idea
\r
2026 bool VideoWin::supportsAc3(){
\r
2027 if (sourcefilter != NULL) {
\r
2028 return sourcefilter->supportsAc3();
\r
2034 bool VideoWin::supportsh264()
\r
2036 if (videoH264filterlist.size()>0) return true;
\r
2037 else return false;
\r
2041 bool VideoWin::changeAType(int type,IMediaSample* ms){
\r
2042 if (sourcefilter!= NULL) {
\r
2043 lastaudiomode=type;
\r
2044 return sourcefilter->changeAType(type,ms);
\r
2053 int VideoWin::test()
\r
2058 int VideoWin::test2()
\r