2 Copyright 2004-2005 Chris Tallon
4 This file is part of VOMP.
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.
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.
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.
23 #include "dssourcefilter.h"
24 #include "dsallocator.h"
28 #include "wwinvideofilter.h"
30 #include "woptionpane.h"
49 lastaudiomode=MPTYPE_MPEG_AUDIO;
50 //lastaudiomode=MPTYPE_AC3;
52 filtermutex=CreateMutex(NULL,FALSE,NULL);
54 offsetvideonotset=true;
55 offsetaudionotset=true;
62 cur_audio_media_sample=NULL;
63 cur_video_media_sample=NULL;
70 aud_type=Audio::MPEG2_PES;
71 iframemode=false;//We are not in Iframe mode at begining
72 vmrdeinterlacing=2;//Best
73 videofilterselected=-1;
83 CloseHandle(filtermutex);
85 for (i=0;i<videofilterlist.size();i++)
87 if (videofilterlist[i].displayname) delete [] videofilterlist[i].displayname;
88 if (videofilterlist[i].friendlyname) delete [] videofilterlist[i].friendlyname;
90 videofilterlist.clear();
98 int VideoWin::init(UCHAR tformat)
100 if (initted) return 0;
103 tvsize=Video::ASPECT16X9; //Internally Vomp should think we are a 16:9 TV
106 initFilterDatabase();
108 if (!setFormat(tformat)){ shutdown(); return 0; }
114 int VideoWin::setTVsize(UCHAR ttvsize)
116 pseudotvsize=ttvsize;
120 int VideoWin::setDefaultAspect()
122 return setAspectRatio(Video::ASPECT4X3);
125 int VideoWin::shutdown()
127 if (!initted) return 0;
132 int VideoWin::setFormat(UCHAR tformat)
134 if (!initted) return 0;
135 if ((tformat != PAL) && (tformat != NTSC)) return 0;
151 int VideoWin::setConnection(UCHAR tconnection)
153 if (!initted) return 0;
154 if ((tconnection != COMPOSITERGB) && (tconnection != SVIDEO)) return 0;
155 connection = tconnection;
160 int VideoWin::setAspectRatio(UCHAR taspectRatio)
162 if (!initted) return 0;
163 if ((taspectRatio != ASPECT4X3) && (taspectRatio != ASPECT16X9)) return 0;
164 aspectRatio = taspectRatio;
169 int VideoWin::setMode(UCHAR tmode)
171 if (!initted) return 0;
173 //if ((tmode == LETTERBOX) && (tvsize == ASPECT16X9)) return 0; // invalid mode
175 if ((tmode != NORMAL) && (tmode != LETTERBOX) && (tmode != UNKNOWN2) && (tmode != QUARTER) && (tmode != EIGHTH)
176 && (tmode != ZOOM) && (tmode != UNKNOWN6)) return 0;
185 int VideoWin::signalOff()
190 int VideoWin::signalOn()
195 int VideoWin::setSource()
197 if (!initted) return 0;
202 int VideoWin::setPosition(int x, int y)
204 if (!initted) return 0;
205 if (mode==QUARTER || mode==EIGHTH) {
214 if (!initted) return 0;
218 void VideoWin::initFilterDatabase()
220 /* This method should determine all availiable DirectShow Filters */
221 IFilterMapper2* filtmap=NULL;
223 result = CoCreateInstance(CLSID_FilterMapper2,NULL,CLSCTX_INPROC,
224 IID_IFilterMapper2,(void**)&filtmap);
227 Log::getInstance()->log("VideoWin", Log::ERR , "Unable to create FilterMapper!");
230 /* Wishlist, what Mediatypes do we want */
231 GUID mtypesin[]={MEDIATYPE_Video,MEDIASUBTYPE_MPEG2_VIDEO};
232 IEnumMoniker *myenum;
233 result = filtmap->EnumMatchingFilters(&myenum,0,TRUE,MERIT_DO_NOT_USE+1,
234 TRUE,1,mtypesin,NULL,NULL,FALSE,TRUE,0,NULL,NULL,NULL);
238 Log::getInstance()->log("VideoWin", Log::ERR , "Unable to enum Filters!");
243 while(myenum->Next(1,&moni,&gethowmany)==S_OK)
245 VideoFilterDesc desc;
246 ZeroMemory(&desc,sizeof(desc));
249 moni->GetDisplayName(0,0,&string);
250 desc.displayname=new char[wcslen(string)+1];
251 wcstombs(desc.displayname,string,wcslen(string)+1);
252 CoTaskMemFree(string);
254 if (moni->BindToStorage(0,0,IID_IPropertyBag,(void**)&bag) == S_OK)
258 result = bag->Read(L"FriendlyName",&vari,NULL);
261 desc.friendlyname=new char[wcslen(vari.bstrVal)+1];
262 wcstombs(desc.friendlyname,vari.bstrVal,wcslen(vari.bstrVal)+1);
270 videofilterlist.push_back(desc);
278 videofilterselected=-1;
289 bool VideoWin::loadOptionsfromServer(VDR* vdr)
291 char *name=vdr->configLoad("DirectShow","VideoFilter");
295 for (int i = 0;i <videofilterlist.size();i++)
297 if (strcmp(name,videofilterlist[i].displayname)==0)
299 videofilterselected = i;
304 name=vdr->configLoad("DirectShow","VMR9DeinterlacingMode");
307 if (STRCASECMP(name,"NoMix")==0) {
309 } else if (STRCASECMP(name,"None")==0) {
311 } else if (STRCASECMP(name,"Best")==0) {
313 } else if (STRCASECMP(name,"Bob")==0) {
315 } else if (STRCASECMP(name,"Weave")==0) {
320 name=vdr->configLoad("DirectGraphics", "StretchFiltering");
322 if (STRCASECMP(name,"None")==0) {
323 ((OsdWin*)Osd::getInstance())->setFilterType(D3DTEXF_NONE);
324 } else if (STRCASECMP(name,"Point")==0) {
325 ((OsdWin*)Osd::getInstance())->setFilterType(D3DTEXF_POINT);
326 } else if (STRCASECMP(name,"Linear")==0) {
327 ((OsdWin*)Osd::getInstance())->setFilterType(D3DTEXF_LINEAR);
336 bool VideoWin::handleOptionChanges(Option* option)
338 if( Video::handleOptionChanges(option)) return true;
341 if (STRCASECMP(option->options[option->userSetChoice],"None")==0) {
342 ((OsdWin*)Osd::getInstance())->setFilterType(D3DTEXF_NONE);
343 } else if (STRCASECMP(option->options[option->userSetChoice],"Point")==0) {
344 ((OsdWin*)Osd::getInstance())->setFilterType(D3DTEXF_POINT);
345 } else if (STRCASECMP(option->options[option->userSetChoice],"Linear")==0) {
346 ((OsdWin*)Osd::getInstance())->setFilterType(D3DTEXF_LINEAR);
351 if (STRCASECMP(option->options[option->userSetChoice],"NoMix")==0) {
353 } else if (STRCASECMP(option->options[option->userSetChoice],"None")==0) {
355 } else if (STRCASECMP(option->options[option->userSetChoice],"Best")==0) {
357 } else if (STRCASECMP(option->options[option->userSetChoice],"Bob")==0) {
359 } else if (STRCASECMP(option->options[option->userSetChoice],"Weave")==0) {
368 bool VideoWin::saveOptionstoServer()
370 if (videofilterselected!=-1) {
371 VDR::getInstance()->configSave("DirectShow",
372 "VideoFilter",videofilterlist[videofilterselected].displayname);
377 /*Option(UINT id, const char* displayText, const char* configSection, const char* configKey, UINT optionType,
378 UINT numChoices, UINT defaultChoice, UINT startInt,
379 const char * const * options, const char * const * optionkeys = NULL, AbstractOption* handler=NULL);*/
381 bool VideoWin::addOptionsToPanes(int panenumber,Options *options,WOptionPane* pane)
383 if (!Video::addOptionsToPanes(panenumber,options,pane)) return false;
389 DWORD scalingcaps=((OsdWin*)Osd::getInstance())->getFilterCaps();
390 char **scalingopts=new char *[3];
392 scalingopts[i]=new char[strlen("None")+1];
393 strcpy(scalingopts[i],"None");
395 if ((scalingcaps & D3DPTFILTERCAPS_MINFPOINT)!=0
396 && (scalingcaps & D3DPTFILTERCAPS_MAGFPOINT)!=0) {
397 scalingopts[i]=new char[strlen("Point")+1];
398 strcpy(scalingopts[i],"Point");
401 if ((scalingcaps & D3DPTFILTERCAPS_MINFLINEAR)!=0
402 && (scalingcaps & D3DPTFILTERCAPS_MAGFLINEAR)!=0) {
403 scalingopts[i]=new char[strlen("Linear")+1];
404 strcpy(scalingopts[i],"Linear");
407 option = new Option(1 , "Video Stretching Filter", "DirectGraphics", "StretchFiltering", Option::TYPE_TEXT, i, (i-1), 0, scalingopts,NULL,true, this);
408 options->push_back(option);
409 pane->addOptionLine(option);
410 static const char* deintopts[]={"NoMix","None","Best","Bob","Weave"};
411 option = new Option(2,"VMR9 Deinterlacing Mode", "DirectShow","VMR9DeinterlacingMode",Option::TYPE_TEXT,5,2,0,deintopts,NULL,false,this);
412 options->push_back(option);
413 pane->addOptionLine(option);
421 IBaseFilter *VideoWin::getVideoFilter()
423 IBaseFilter *curfilter= NULL;
424 if (videofilterselected == -1)
427 for (i = 0;i <videofilterlist.size();i++)
430 if (videofilterlist[i].vmr9tested == true)
432 if (videofilterlist[i].vmr9 == true)
434 videofilterselected = i;
444 IMoniker * moni=NULL;
445 IBindCtx *bindctx=NULL;
446 if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
447 LPCOLESTR name=(LPCOLESTR)new WCHAR[strlen(videofilterlist[i].displayname)+1];
448 mbstowcs((wchar_t*)name,videofilterlist[i].displayname,strlen(videofilterlist[i].displayname)+1);
452 if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
454 if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
456 IAMDecoderCaps* desccaps=NULL;
457 if (curfilter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK)
460 desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps);
461 if (caps == DECODER_CAP_SUPPORTED)
463 videofilterlist[i].vmr9tested = true;
464 videofilterlist[i].vmr9 = true;
465 videofilterselected = i;
469 videofilterlist[i].vmr9tested = true;
470 videofilterlist[i].vmr9 = false;
472 curfilter->Release();
483 if (videofilterlist[i].vmr9) break;
486 if (curfilter != NULL)
488 VDR *vdr=VDR::getInstance();
491 vdr->configSave("DirectShow","VideoFilter",
492 videofilterlist[videofilterselected].displayname);
499 IBindCtx *bindctx=NULL;
500 if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
501 IMoniker * moni=NULL;
502 LPCOLESTR name=new WCHAR[strlen(videofilterlist[videofilterselected].displayname)+1];
503 mbstowcs((wchar_t*)name,videofilterlist[videofilterselected].displayname,
504 strlen(videofilterlist[videofilterselected].displayname)+1);
506 if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
508 if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
510 IAMDecoderCaps* desccaps=NULL;
511 if (curfilter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK)
514 desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps);
515 if (caps == DECODER_CAP_SUPPORTED)
517 videofilterlist[videofilterselected].vmr9tested = true;
518 videofilterlist[videofilterselected].vmr9 = true;
522 videofilterlist[videofilterselected].vmr9tested = true;
523 videofilterlist[videofilterselected].vmr9 = false;
524 Log::getInstance()->log("VideoWin", Log::WARN ,"Filter does not support VMR9, but is selected, manual selection!");
543 #ifdef DS_DEBUG // This stuff would not included in vomp due to lincemse restrcitions
544 #include "dshelper.h"
551 if (!initted) return 0;
555 bool VideoWin::addOptionPagesToWTB(WTabBar *wtb)
557 Boxx *box=new WWinVideoFilter();
558 wtb->addTab(tr("Video Filter"), box);
562 const VideoFilterDescList *VideoWin::getVideoFilterList(int &selected)
564 selected=videofilterselected;
565 return &videofilterlist;
568 bool VideoWin::selectVideoFilter(int filter)
570 IBindCtx *bindctx=NULL;
571 if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
572 IMoniker * moni=NULL;
573 LPCOLESTR name=new WCHAR[strlen(videofilterlist[filter].displayname)+1];
574 mbstowcs((wchar_t*)name,videofilterlist[filter].displayname,
575 strlen(videofilterlist[filter].displayname)+1);
578 if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
580 IBaseFilter* curfilter=NULL;
581 if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
583 IAMDecoderCaps* desccaps=NULL;
584 if (curfilter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK)
587 HRESULT hres=desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps);
588 if (caps == DECODER_CAP_SUPPORTED)
590 videofilterlist[filter].vmr9tested = true;
591 videofilterlist[filter].vmr9 = true;
596 videofilterlist[filter].vmr9tested = true;
597 videofilterlist[filter].vmr9 = false;
602 videofilterlist[filter].vmr9tested = true;
603 videofilterlist[filter].vmr9 = false;
607 curfilter->Release();
616 videofilterselected=filter;
626 int VideoWin::dsInitVideoFilter()
631 //We alloc the vmr9 as next step
632 if (hres=CoCreateInstance(CLSID_VideoMixingRenderer9,0,
633 CLSCTX_INPROC_SERVER,IID_IBaseFilter,(void**) &dsvmrrenderer)!=S_OK)
635 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed creating VMR9 renderer!");
636 ReleaseMutex(filtermutex);
640 if (hres=dsgraphbuilder->AddFilter(dsvmrrenderer,L"VMR9")!=S_OK)
642 ReleaseMutex(filtermutex);
644 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed adding VMR9 renderer!");
647 IVMRFilterConfig9* vmrfilconfig;
648 if (dsvmrrenderer->QueryInterface(IID_IVMRFilterConfig9,(void**)&vmrfilconfig)!=S_OK)
650 ReleaseMutex(filtermutex);
652 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Filterconfig interface!");
655 if (vmrdeinterlacing!=0) vmrfilconfig->SetNumberOfStreams(1);//Enter Mixing Mode
656 vmrfilconfig->SetRenderingMode(VMR9Mode_Renderless);
658 vmrfilconfig->Release();
660 if (dsvmrrenderer->QueryInterface(IID_IVMRSurfaceAllocatorNotify9,
661 (void**)& dsvmrsurfnotify) != S_OK)
663 ReleaseMutex(filtermutex);
665 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Surface Allocator interface!");
668 allocatorvmr=new DsAllocator();
669 dsvmrsurfnotify->AdviseSurfaceAllocator(NULL,allocatorvmr);
670 allocatorvmr->AdviseNotify(dsvmrsurfnotify);
672 IVMRDeinterlaceControl9* deintctrl;
673 if (dsvmrrenderer->QueryInterface(IID_IVMRDeinterlaceControl9,(void**)&deintctrl)!=S_OK)
675 ReleaseMutex(filtermutex);
677 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Deinterlace control!");
681 switch (vmrdeinterlacing)
683 case 1: //No Deinterlasing
684 deintctrl->SetDeinterlaceMode(0xFFFFFFFF,(LPGUID)&GUID_NULL);//Turn Off
687 deintctrl->SetDeinterlacePrefs(DeinterlacePref_NextBest);//Choose Next Best
691 deintctrl->SetDeinterlacePrefs(DeinterlacePref_BOB);//Choose NBob
694 deintctrl->SetDeinterlacePrefs(DeinterlacePref_Weave);//Choose Weave
697 deintctrl->Release();
700 IFilterGraph2*fg2=NULL;
701 if (dsgraphbuilder->QueryInterface(IID_IFilterGraph2,(void**)&fg2)!= S_OK)
703 Log::getInstance()->log("VideoWin", Log::WARN , "Failed querying for FilterGraph2 Interface!");
704 ReleaseMutex(filtermutex);
708 /*#ifndef NEW_DS_MECHANISMENS
710 if (hres=fg2->RenderEx((IPin*)sourcefilter->GetVideoPin()/*video*,
711 AM_RENDEREX_RENDERTOEXISTINGRENDERERS,NULL) != S_OK)
713 Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering Video!");
715 ReleaseMutex(filtermutex);
721 IBaseFilter*videofilter=getVideoFilter();
722 if (hres=dsgraphbuilder->AddFilter(videofilter,NULL) != S_OK)
724 Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Video Filter!");
725 ReleaseMutex(filtermutex);
729 IEnumPins *pinenum=NULL;
731 if (videofilter->EnumPins(&pinenum) == S_OK)
735 bool firststep=false;
737 while (pinenum->Next(1,¤t,&fetch)==S_OK)
740 if (current->QueryDirection(&dir)==S_OK)
742 if (dir == PINDIR_INPUT)
744 if (sourcefilter->GetVideoPin()->Connect(current,NULL)==S_OK)
754 if (firststep==false)
756 Log::getInstance()->log("VideoWin", Log::WARN , "Video Filter has no suitable input!");
757 videofilter->Release();
758 ReleaseMutex(filtermutex);
762 bool secondstep=false;
764 while (pinenum->Next(1,¤t,&fetch)==S_OK)
767 if (current->QueryDirection(&dir)==S_OK)
769 if (dir == PINDIR_OUTPUT)
772 if (fg2->RenderEx((IPin*)current/*video*/,
773 AM_RENDEREX_RENDERTOEXISTINGRENDERERS,NULL) ==S_OK)
783 if (secondstep==false)
785 Log::getInstance()->log("VideoWin", Log::WARN , "Video Filter has no suitable output!");
786 videofilter->Release();
787 ReleaseMutex(filtermutex);
792 videofilter->Release();
806 int VideoWin::setAudioStreamType(UCHAR type)
809 if (!initted) return 0;
813 int VideoWin::dsplay()
815 if (!initted) return 0;
820 //So this is the real code, this prevents the feeder from calling noexisting objects!
821 WaitForSingleObject(filtermutex,INFINITE);
822 if (hres=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,
823 IID_IGraphBuilder,(void**)&dsgraphbuilder) != S_OK)
825 ReleaseMutex(filtermutex);
829 AddToRot(dsgraphbuilder,&graphidentifier);
833 if (aud_type==Audio::MP3) {
834 lastaudiomode=MPTYPE_MPEG_AUDIO_LAYER3;
836 lastaudiomode=MPTYPE_MPEG_AUDIO;
838 //lastaudiomode=MPTYPE_AC3;
839 sourcefilter=new DsSourceFilter(); //Creating our Source filter for pushing Data
841 if (hres=dsgraphbuilder->AddFilter(sourcefilter,L"Vomp Win Source Filter") != S_OK)
843 Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Vomp Source Filter!");
844 ReleaseMutex(filtermutex);
848 sourcefilter->GetAudioPin()->SetPinMode(lastaudiomode);
849 /*if (hres=dsgraphbuilder->Render((IPin*)sourcefilter->GetAudioPin()/*audio*)!=S_OK)
851 Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering audio!");
852 ReleaseMutex(filtermutex);
856 if (((AudioWin*)Audio::getInstance())->dsInitAudioFilter(dsgraphbuilder)==0)
858 Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering audio!");
859 ReleaseMutex(filtermutex);
865 if (dsInitVideoFilter()==0)
870 if (hres=CoCreateInstance(CLSID_SystemClock,NULL,CLSCTX_INPROC_SERVER,
871 IID_IReferenceClock,(void**)&dsrefclock)!=S_OK)
875 dsgraphbuilder->QueryInterface(IID_IMediaFilter,(void **) &dsmediafilter);
876 HRESULT hresdeb = dsmediafilter->SetSyncSource(dsrefclock);
878 dsgraphbuilder->QueryInterface(IID_IMediaControl,(void **) &dsmediacontrol);
879 dsgraphbuilder->QueryInterface(IID_IBasicAudio,(void **) &dsbasicaudio);
881 dsbasicaudio->put_Volume(audiovolume);
885 hresdeb=dsmediacontrol->Run();
886 iframemode=false;//exit iframe mode
887 ReleaseMutex(filtermutex);
891 int VideoWin::EnterIframePlayback()
893 if (!initted) return 0;
895 //So this is the real code, this prevents the feeder from calling noexisting objects!
896 WaitForSingleObject(filtermutex,INFINITE);
897 iframemode=true;//enter iframe mode
900 if (hres=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,
901 IID_IGraphBuilder,(void**)&dsgraphbuilder)!=S_OK) {
902 ReleaseMutex(filtermutex);
906 AddToRot(dsgraphbuilder,&graphidentifier);
909 //firstsynched=false;
910 sourcefilter=new DsSourceFilter(); //Creating our Source filter for pushing Data
912 if (hres=dsgraphbuilder->AddFilter(sourcefilter,L"Vomp Win Source Filter")!=S_OK) {
913 Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Vomp Source Filter!");
914 ReleaseMutex(filtermutex);
923 /* if (hres=CoCreateInstance(CLSID_SystemClock,NULL,CLSCTX_INPROC_SERVER,
924 IID_IReferenceClock,(void**)&dsrefclock)!=S_OK) {
928 dsgraphbuilder->QueryInterface(IID_IMediaFilter,(void **) &dsmediafilter);
929 dsmediafilter->SetSyncSource(/*dsrefclock*/NULL); //Run as fast as you can!
931 dsgraphbuilder->QueryInterface(IID_IMediaControl,(void **) &dsmediacontrol);
932 dsgraphbuilder->QueryInterface(IID_IBasicAudio,(void **) &dsbasicaudio);
936 dsmediacontrol->Run();
937 ReleaseMutex(filtermutex);
942 int VideoWin::dsstop()
944 if (!initted) return 0;
954 if (!initted) return 0;
960 int VideoWin::reset()
962 if (!initted) return 0;
968 int VideoWin::dsreset()
970 if (!initted) return 0;
973 iframemode=false;//exit iframe mode
979 int VideoWin::dspause()
981 if (!initted) return 0;
982 WaitForSingleObject(filtermutex,INFINITE);
983 if (dsmediacontrol) dsmediacontrol->Pause();
984 ReleaseMutex(filtermutex);
988 int VideoWin::pause()
990 if (!initted) return 0;
995 int VideoWin::unPause() // FIXME get rid - same as play!!
996 {//No on windows this is not the same, I don't get rid of!
997 if (!initted) return 0;
1001 int VideoWin::dsunPause() // FIXME get rid - same as play!!
1002 {//No on windows this is not the same, I don't get rid of!
1003 if (!initted) return 0;
1004 WaitForSingleObject(filtermutex,INFINITE);
1005 if (dsmediacontrol) dsmediacontrol->Run();
1006 ReleaseMutex(filtermutex);
1011 int VideoWin::fastForward()
1013 if (!initted) return 0;
1018 int VideoWin::unFastForward()
1020 if (!initted) return 0;
1025 int VideoWin::attachFrameBuffer()
1027 if (!initted) return 0;
1031 int VideoWin::blank(void)
1033 ((OsdWin*)Osd::getInstance())->Blank();
1037 ULLONG VideoWin::getCurrentTimestamp()
1039 REFERENCE_TIME startoffset;
1040 REFERENCE_TIME ncr_time;
1041 if (iframemode) return 0; //Not in iframe mode!
1042 if (!dsrefclock || !sourcefilter) return 0;
1044 sourcefilter->GetState(10,&state);
1046 if (state==State_Running) dsrefclock->GetTime(&cr_time);
1048 startoffset=sourcefilter->getStartOffset();
1049 ncr_time-=startoffset;
1050 ncr_time-=lastreftimeRT;
1051 /* ULLONG result=frameNumberToTimecode(
1052 VDR::getInstance()->frameNumberFromPosition(lastreftimeBYTE));*/
1053 ULLONG result=lastreftimePTS;
1054 result+=(ULLONG)(ncr_time/10000LL*90LL);
1059 ULONG VideoWin::timecodeToFrameNumber(ULLONG timecode)
1061 if (format == PAL) return (ULONG)(((double)timecode / (double)90000) * (double)25);
1062 else return (ULONG)(((double)timecode / (double)90000) * (double)30);
1065 ULLONG VideoWin::frameNumberToTimecode(ULONG framenumber)
1067 if (format == PAL) return (ULLONG)(((double)framenumber * (double)90000) / (double)25);
1068 else return (ULLONG)(((double)framenumber * (double)90000) / (double)30);
1071 void VideoWin::CleanupDS()
1073 WaitForSingleObject(filtermutex,INFINITE);
1075 if (dsmediacontrol)dsmediacontrol->Stop();
1076 if (cur_audio_media_sample) {
1077 cur_audio_media_sample->Release();
1078 cur_audio_media_sample=NULL;
1080 if (cur_video_media_sample) {
1081 cur_video_media_sample->Release();
1082 cur_video_media_sample=NULL;
1085 dsbasicaudio->Release();
1088 if (dsvmrsurfnotify) {
1089 dsvmrsurfnotify->Release();
1090 dsvmrsurfnotify=NULL;
1092 if (dsvmrrenderer) {
1093 dsvmrrenderer->Release();
1098 allocatorvmr->Release();
1103 dsrefclock->Release();
1106 if (dsmediafilter) {
1107 dsmediafilter->Release();
1113 if (dsmediacontrol) {
1114 dsmediacontrol->Stop();
1115 dsmediacontrol->Release();
1116 dsmediacontrol=NULL;
1118 if (dsgraphbuilder){
1120 RemoveFromRot(graphidentifier);
1122 dsgraphbuilder->Release();
1123 dsgraphbuilder=NULL;
1125 sourcefilter=NULL; //The Graph Builder destroys our SourceFilter
1127 ReleaseMutex(filtermutex);
1131 void VideoWin::PrepareMediaSample(const MediaPacketList& mplist,
1134 mediapacket = mplist.front();
1137 UINT VideoWin::DeliverMediaSample(const UCHAR* buffer, UINT *samplepos)
1139 DeliverMediaPacket(mediapacket, buffer, samplepos);
1140 if (*samplepos == mediapacket.length) {
1147 UINT VideoWin::DeliverMediaPacket(MediaPacket packet,
1148 const UCHAR* buffer,
1152 /*First Check, if we have an audio sample*/
1153 if (!isdsinited()) return 0;
1156 *samplepos+=packet.length;
1157 MILLISLEEP(0); //yet not implemented//bad idea
1158 return packet.length;
1160 /*First Check, if we have an audio sample*/
1164 return 0; //Not in iframe mode!
1166 IMediaSample* ms=NULL;
1167 REFERENCE_TIME reftime1=0;
1168 REFERENCE_TIME reftime2=0;
1171 if (packet.disconti) {
1173 DeliverVideoMediaSample();
1176 /*Inspect PES-Header */
1178 if (*samplepos==0) {//stripheader
1179 headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/;
1180 *samplepos+=headerstrip;
1181 if ( packet.synched ) {
1182 DeliverVideoMediaSample();//write out old data
1183 /* if (packet.presentation_time<0) { //Preroll?
1184 *samplepos=packet.length;//if we have not processed at least one
1185 return packet.length;//synched packet ignore it!
1188 reftime1=packet.presentation_time;
1189 reftime2=reftime1+1;
1192 if (!firstsynched) {//
1193 *samplepos=packet.length;//if we have not processed at least one
1194 return packet.length;//synched packet ignore it!
1203 if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
1208 ms_pos=ms->GetActualDataLength();
1209 ms_length=ms->GetSize();
1210 haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);
1211 if ((ms_length-ms_pos)<1) {
1212 DeliverVideoMediaSample(); //we are full!
1213 if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
1218 ms_pos=ms->GetActualDataLength();
1219 ms_length=ms->GetSize();
1220 haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);
1222 ms->GetPointer(&ms_buf);
1225 if (ms_pos==0) {//will only be changed on first packet
1226 if (packet.disconti) {
1227 ms->SetDiscontinuity(TRUE);
1229 ms->SetDiscontinuity(FALSE);
1231 if (packet.synched) {
1232 ms->SetSyncPoint(TRUE);
1233 ms->SetTime(&reftime1,&reftime2);
1234 //ms->SetTime(NULL,NULL);
1235 ms->SetMediaTime(NULL, NULL);
1236 if (reftime1<0) ms->SetPreroll(TRUE);
1237 else ms->SetPreroll(FALSE);
1238 /*Timecode handling*/
1239 lastreftimeRT=reftime1;
1240 lastreftimePTS=packet.pts;
1243 ms->SetSyncPoint(FALSE);
1244 ms->SetTime(NULL,NULL);
1245 ms->SetMediaTime(NULL, NULL);
1246 ms->SetPreroll(FALSE);
1248 // ms->SetSyncPoint(TRUE);
1253 memcpy(ms_buf+ms_pos,buffer+packet.pos_buffer+*samplepos,haveToCopy);
1254 ms->SetActualDataLength(haveToCopy+ms_pos);
1256 *samplepos+=haveToCopy;
1258 return haveToCopy+headerstrip;
1262 *samplepos+=packet.length;
1263 MILLISLEEP(0); //yet not implemented//bad idea
1264 return packet.length;
1268 int VideoWin::getCurrentAudioMediaSample(IMediaSample** ms)
1270 //WaitForSingleObject(filtermutex,INFINITE);
1272 // ReleaseMutex(filtermutex);
1275 if (cur_audio_media_sample) {
1276 *ms=cur_audio_media_sample;//already open
1279 if (!sourcefilter->getCurrentAudioMediaSample(ms)) {
1280 // ReleaseMutex(filtermutex);
1282 if (*ms) (*ms)->SetActualDataLength(0);
1283 cur_audio_media_sample=*ms;
1284 //Don't release the mutex before deliver
1288 int VideoWin::getCurrentVideoMediaSample(IMediaSample** ms)
1290 //WaitForSingleObject(filtermutex,INFINITE);
1292 // ReleaseMutex(filtermutex);
1295 if (cur_video_media_sample) {
1296 *ms=cur_video_media_sample;//already open
1299 if (!sourcefilter->getCurrentVideoMediaSample(ms)) {
1300 // ReleaseMutex(filtermutex);
1302 if (*ms) (*ms)->SetActualDataLength(0);
1304 cur_video_media_sample=*ms;
1305 //Don't release the mutex before deliver
1309 int VideoWin::DeliverAudioMediaSample(){
1310 if (cur_audio_media_sample) {
1311 sourcefilter->DeliverAudioMediaSample(cur_audio_media_sample);
1312 cur_audio_media_sample=NULL;
1314 //ReleaseMutex(filtermutex);
1318 int VideoWin::DeliverVideoMediaSample(){
1319 if (cur_video_media_sample) {
1320 sourcefilter->DeliverVideoMediaSample(cur_video_media_sample);
1321 cur_video_media_sample=NULL;
1323 //ReleaseMutex(filtermutex);
1327 long long VideoWin::SetStartOffset(long long curreftime, bool *rsync)
1331 startoffset=curreftime;//offset is set for audio
1333 offsetvideonotset=false;
1337 if (offsetvideonotset) {
1338 offsetvideonotset=false;
1341 if ( (curreftime-lastrefvideotime)>10000000LL
1342 || (curreftime-lastrefvideotime)<-10000000LL) {//if pts jumps to big resync
1343 startoffset+=curreftime-lastrefvideotime;
1344 lastrefaudiotime+=curreftime-lastrefvideotime;
1346 offsetaudionotset=true;
1353 lastrefvideotime=curreftime;
1359 long long VideoWin::SetStartAudioOffset(long long curreftime, bool *rsync)
1363 startoffset=curreftime;
1365 offsetaudionotset=false;
1367 if (offsetaudionotset) {
1368 offsetaudionotset=false;
1371 if ( (curreftime-lastrefaudiotime)>10000000LL
1372 || (curreftime-lastrefaudiotime)<-10000000LL) {//if pts jumps to big resync
1373 startoffset+=curreftime-lastrefaudiotime;
1374 lastrefvideotime+=curreftime-lastrefaudiotime;
1376 offsetvideonotset=true;
1382 lastrefaudiotime=curreftime;
1386 void VideoWin::ResetTimeOffsets() {
1387 offsetnotset=true; //called from demuxer
1388 offsetvideonotset=true;
1389 offsetaudionotset=true;
1399 void VideoWin::SetAudioVolume(long volume)
1402 if (dsbasicaudio) dsbasicaudio->put_Volume(volume);
1405 void VideoWin::displayIFrame(const UCHAR* buffer, UINT length)
1407 if (!iframemode) EnterIframePlayback();
1409 if (!isdsinited()) return ;
1411 IMediaSample* ms=NULL;
1412 REFERENCE_TIME reftime1=0;
1413 REFERENCE_TIME reftime2=0;
1414 if (!videoon) return;
1416 if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
1422 ms->GetPointer(&ms_buf);
1423 ms_length=ms->GetSize();
1425 /*First Check, if we have an video sample*/
1426 DWORD read_pos = 0, write_pos = 0;
1427 DWORD pattern, packet_length;
1428 DWORD headerstrip=0;
1430 if (length < 4) return ;
1431 //Now we strip the pes header
1432 pattern = (buffer[0] << 16) | (buffer[1] << 8) | (buffer[2]);
1433 while (read_pos + 7 <= length)
1435 pattern = ((pattern << 8) & 0xFFFFFFFF) | buffer[read_pos+3];
1436 if (pattern < 0x000001E0 || pattern > 0x000001EF)
1440 headerstrip=buffer[read_pos+8]+9/*is this right*/;
1441 packet_length = ((buffer[read_pos+4] << 8) | (buffer[read_pos+5])) + 6;
1442 if (read_pos + packet_length > length)
1446 if ((write_pos+packet_length-headerstrip)>ms_length) {
1448 ms->SetSyncPoint(TRUE);
1449 ms->SetDiscontinuity(TRUE);
1451 } else ms->SetSyncPoint(FALSE);
1452 ms->SetTime(NULL,NULL);
1453 ms->SetMediaTime(NULL, NULL);
1454 ms->SetActualDataLength(write_pos);
1455 DeliverVideoMediaSample();
1457 if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
1462 ms_length=ms->GetSize();
1463 ms->GetPointer(&ms_buf);
1465 if (packet_length>headerstrip) {
1466 memcpy(ms_buf+write_pos, buffer+read_pos+headerstrip, packet_length-headerstrip);
1467 write_pos += packet_length-headerstrip;
1469 read_pos += packet_length;
1471 pattern = (buffer[read_pos] << 16) | (buffer[read_pos+1] << 8)
1472 | (buffer[read_pos+2]);
1477 if (first) {ms->SetSyncPoint(TRUE);first=false;}
1478 else ms->SetSyncPoint(FALSE);
1479 ms->SetTime(NULL,NULL);
1480 ms->SetMediaTime(NULL, NULL);
1481 ms->SetActualDataLength(write_pos);
1482 DeliverVideoMediaSample();
1486 // *samplepos+=packet.length;
1487 MILLISLEEP(0); //yet not implemented//bad idea
1492 bool VideoWin::supportsAc3(){
1493 if (sourcefilter != NULL) {
1494 return sourcefilter->supportsAc3();
1500 bool VideoWin::changeAType(int type,IMediaSample* ms){
1501 if (sourcefilter!= NULL) {
1503 return sourcefilter->changeAType(type,ms);
1512 int VideoWin::test()
1517 int VideoWin::test2()