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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "dssourcefilter.h"
24 #include "dsallocator.h"
28 #include "wwinvideofilter.h"
48 lastaudiomode=MPTYPE_MPEG_AUDIO;
49 //lastaudiomode=MPTYPE_AC3;
51 filtermutex=CreateMutex(NULL,FALSE,NULL);
53 offsetvideonotset=true;
54 offsetaudionotset=true;
61 cur_audio_media_sample=NULL;
62 cur_video_media_sample=NULL;
69 aud_type=Audio::MPEG2_PES;
70 iframemode=false;//We are not in Iframe mode at begining
72 videofilterselected=-1;
82 CloseHandle(filtermutex);
84 for (i=0;i<videofilterlist.size();i++)
86 if (videofilterlist[i].displayname) delete [] videofilterlist[i].displayname;
87 if (videofilterlist[i].friendlyname) delete [] videofilterlist[i].friendlyname;
89 videofilterlist.clear();
97 int VideoWin::init(UCHAR tformat)
99 if (initted) return 0;
102 tvsize=Video::ASPECT16X9; //Internally Vomp should think we are a 16:9 TV
105 initFilterDatabase();
107 if (!setFormat(tformat)){ shutdown(); return 0; }
113 int VideoWin::setTVsize(UCHAR ttvsize)
115 pseudotvsize=ttvsize;
119 int VideoWin::setDefaultAspect()
121 return setAspectRatio(Video::ASPECT4X3);
124 int VideoWin::shutdown()
126 if (!initted) return 0;
131 int VideoWin::setFormat(UCHAR tformat)
133 if (!initted) return 0;
134 if ((tformat != PAL) && (tformat != NTSC)) return 0;
150 int VideoWin::setConnection(UCHAR tconnection)
152 if (!initted) return 0;
153 if ((tconnection != COMPOSITERGB) && (tconnection != SVIDEO)) return 0;
154 connection = tconnection;
159 int VideoWin::setAspectRatio(UCHAR taspectRatio)
161 if (!initted) return 0;
162 if ((taspectRatio != ASPECT4X3) && (taspectRatio != ASPECT16X9)) return 0;
163 aspectRatio = taspectRatio;
168 int VideoWin::setMode(UCHAR tmode)
170 if (!initted) return 0;
172 //if ((tmode == LETTERBOX) && (tvsize == ASPECT16X9)) return 0; // invalid mode
174 if ((tmode != NORMAL) && (tmode != LETTERBOX) && (tmode != UNKNOWN2) && (tmode != QUARTER) && (tmode != EIGHTH)
175 && (tmode != ZOOM) && (tmode != UNKNOWN6)) return 0;
184 int VideoWin::signalOff()
189 int VideoWin::signalOn()
194 int VideoWin::setSource()
196 if (!initted) return 0;
201 int VideoWin::setPosition(int x, int y)
203 if (!initted) return 0;
204 if (mode==QUARTER || mode==EIGHTH) {
213 if (!initted) return 0;
217 void VideoWin::initFilterDatabase()
219 /* This method should determine all availiable DirectShow Filters */
220 IFilterMapper2* filtmap=NULL;
222 result = CoCreateInstance(CLSID_FilterMapper2,NULL,CLSCTX_INPROC,
223 IID_IFilterMapper2,(void**)&filtmap);
226 Log::getInstance()->log("VideoWin", Log::ERR , "Unable to create FilterMapper!");
229 /* Wishlist, what Mediatypes do we want */
230 GUID mtypesin[]={MEDIATYPE_Video,MEDIASUBTYPE_MPEG2_VIDEO};
231 IEnumMoniker *myenum;
232 result = filtmap->EnumMatchingFilters(&myenum,0,TRUE,MERIT_DO_NOT_USE+1,
233 TRUE,1,mtypesin,NULL,NULL,FALSE,TRUE,0,NULL,NULL,NULL);
237 Log::getInstance()->log("VideoWin", Log::ERR , "Unable to enum Filters!");
242 while(myenum->Next(1,&moni,&gethowmany)==S_OK)
244 VideoFilterDesc desc;
245 ZeroMemory(&desc,sizeof(desc));
248 moni->GetDisplayName(0,0,&string);
249 desc.displayname=new char[wcslen(string)+1];
250 wcstombs(desc.displayname,string,wcslen(string)+1);
251 CoTaskMemFree(string);
253 if (moni->BindToStorage(0,0,IID_IPropertyBag,(void**)&bag) == S_OK)
257 result = bag->Read(L"FriendlyName",&vari,NULL);
260 desc.friendlyname=new char[wcslen(vari.bstrVal)+1];
261 wcstombs(desc.friendlyname,vari.bstrVal,wcslen(vari.bstrVal)+1);
269 videofilterlist.push_back(desc);
277 videofilterselected=-1;
288 bool VideoWin::loadOptionsfromServer(VDR* vdr)
290 char *name=vdr->configLoad("DirectShow","VideoFilter");
294 for (int i = 0;i <videofilterlist.size();i++)
296 if (strcmp(name,videofilterlist[i].displayname)==0)
298 videofilterselected = i;
307 bool VideoWin::saveOptionstoServer()
309 VDR::getInstance()->configSave("DirectShow",
310 "VideoFilter",videofilterlist[videofilterselected].displayname);
314 IBaseFilter *VideoWin::getVideoFilter()
316 IBaseFilter *curfilter= NULL;
317 if (videofilterselected == -1)
320 for (i = 0;i <videofilterlist.size();i++)
323 if (videofilterlist[i].vmr9tested == true)
325 if (videofilterlist[i].vmr9 == true)
327 videofilterselected = i;
337 IMoniker * moni=NULL;
338 IBindCtx *bindctx=NULL;
339 if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
340 LPCOLESTR name=(LPCOLESTR)new WCHAR[strlen(videofilterlist[i].displayname)+1];
341 mbstowcs((wchar_t*)name,videofilterlist[i].displayname,strlen(videofilterlist[i].displayname)+1);
345 if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
347 if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
349 IAMDecoderCaps* desccaps=NULL;
350 if (curfilter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK)
353 desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps);
354 if (caps == DECODER_CAP_SUPPORTED)
356 videofilterlist[i].vmr9tested = true;
357 videofilterlist[i].vmr9 = true;
358 videofilterselected = i;
362 videofilterlist[i].vmr9tested = true;
363 videofilterlist[i].vmr9 = false;
365 curfilter->Release();
376 if (videofilterlist[i].vmr9) break;
379 if (curfilter != NULL)
381 VDR *vdr=VDR::getInstance();
384 vdr->configSave("DirectShow","VideoFilter",
385 videofilterlist[videofilterselected].displayname);
392 IBindCtx *bindctx=NULL;
393 if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
394 IMoniker * moni=NULL;
395 LPCOLESTR name=new WCHAR[strlen(videofilterlist[videofilterselected].displayname)+1];
396 mbstowcs((wchar_t*)name,videofilterlist[videofilterselected].displayname,
397 strlen(videofilterlist[videofilterselected].displayname)+1);
399 if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
401 if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
403 IAMDecoderCaps* desccaps=NULL;
404 if (curfilter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK)
407 desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps);
408 if (caps == DECODER_CAP_SUPPORTED)
410 videofilterlist[videofilterselected].vmr9tested = true;
411 videofilterlist[videofilterselected].vmr9 = true;
415 videofilterlist[videofilterselected].vmr9tested = true;
416 videofilterlist[videofilterselected].vmr9 = false;
417 Log::getInstance()->log("VideoWin", Log::WARN ,"Filter does not support VMR9, but is selected, manual selection!");
436 #ifdef DS_DEBUG // This stuff would not included in vomp due to lincemse restrcitions
437 #include "dshelper.h"
444 if (!initted) return 0;
448 bool VideoWin::addOptionPagesToWTB(WTabBar *wtb)
450 Boxx *box=new WWinVideoFilter();
451 wtb->addTab(tr("Video Filter"), box);
455 const VideoFilterDescList *VideoWin::getVideoFilterList(int &selected)
457 selected=videofilterselected;
458 return &videofilterlist;
461 bool VideoWin::selectVideoFilter(int filter)
463 IBindCtx *bindctx=NULL;
464 if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
465 IMoniker * moni=NULL;
466 LPCOLESTR name=new WCHAR[strlen(videofilterlist[filter].displayname)+1];
467 mbstowcs((wchar_t*)name,videofilterlist[filter].displayname,
468 strlen(videofilterlist[filter].displayname)+1);
471 if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
473 IBaseFilter* curfilter=NULL;
474 if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
476 IAMDecoderCaps* desccaps=NULL;
477 if (curfilter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK)
480 HRESULT hres=desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps);
481 if (caps == DECODER_CAP_SUPPORTED)
483 videofilterlist[filter].vmr9tested = true;
484 videofilterlist[filter].vmr9 = true;
489 videofilterlist[filter].vmr9tested = true;
490 videofilterlist[filter].vmr9 = false;
495 videofilterlist[filter].vmr9tested = true;
496 videofilterlist[filter].vmr9 = false;
500 curfilter->Release();
509 videofilterselected=filter;
519 int VideoWin::dsInitVideoFilter()
524 //We alloc the vmr9 as next step
525 if (hres=CoCreateInstance(CLSID_VideoMixingRenderer9,0,
526 CLSCTX_INPROC_SERVER,IID_IBaseFilter,(void**) &dsvmrrenderer)!=S_OK)
528 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed creating VMR9 renderer!");
529 ReleaseMutex(filtermutex);
533 if (hres=dsgraphbuilder->AddFilter(dsvmrrenderer,L"VMR9")!=S_OK)
535 ReleaseMutex(filtermutex);
537 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed adding VMR9 renderer!");
540 IVMRFilterConfig9* vmrfilconfig;
541 if (dsvmrrenderer->QueryInterface(IID_IVMRFilterConfig9,(void**)&vmrfilconfig)!=S_OK)
543 ReleaseMutex(filtermutex);
545 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Filterconfig interface!");
548 vmrfilconfig->SetRenderingMode(VMR9Mode_Renderless);
549 vmrfilconfig->Release();
551 if (dsvmrrenderer->QueryInterface(IID_IVMRSurfaceAllocatorNotify9,
552 (void**)& dsvmrsurfnotify) != S_OK)
554 ReleaseMutex(filtermutex);
556 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Surface Allocator interface!");
559 allocatorvmr=new DsAllocator();
560 dsvmrsurfnotify->AdviseSurfaceAllocator(NULL,allocatorvmr);
561 allocatorvmr->AdviseNotify(dsvmrsurfnotify);
563 IFilterGraph2*fg2=NULL;
564 if (dsgraphbuilder->QueryInterface(IID_IFilterGraph2,(void**)&fg2)!= S_OK)
566 Log::getInstance()->log("VideoWin", Log::WARN , "Failed querying for FilterGraph2 Interface!");
567 ReleaseMutex(filtermutex);
571 /*#ifndef NEW_DS_MECHANISMENS
573 if (hres=fg2->RenderEx((IPin*)sourcefilter->GetVideoPin()/*video*,
574 AM_RENDEREX_RENDERTOEXISTINGRENDERERS,NULL) != S_OK)
576 Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering Video!");
578 ReleaseMutex(filtermutex);
584 IBaseFilter*videofilter=getVideoFilter();
585 if (hres=dsgraphbuilder->AddFilter(videofilter,NULL) != S_OK)
587 Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Video Filter!");
588 ReleaseMutex(filtermutex);
592 IEnumPins *pinenum=NULL;
594 if (videofilter->EnumPins(&pinenum) == S_OK)
598 bool firststep=false;
600 while (pinenum->Next(1,¤t,&fetch)==S_OK)
603 if (current->QueryDirection(&dir)==S_OK)
605 if (dir == PINDIR_INPUT)
607 if (sourcefilter->GetVideoPin()->Connect(current,NULL)==S_OK)
617 if (firststep==false)
619 Log::getInstance()->log("VideoWin", Log::WARN , "Video Filter has no suitable input!");
620 videofilter->Release();
621 ReleaseMutex(filtermutex);
625 bool secondstep=false;
627 while (pinenum->Next(1,¤t,&fetch)==S_OK)
630 if (current->QueryDirection(&dir)==S_OK)
632 if (dir == PINDIR_OUTPUT)
635 if (fg2->RenderEx((IPin*)current/*video*/,
636 AM_RENDEREX_RENDERTOEXISTINGRENDERERS,NULL) ==S_OK)
646 if (secondstep==false)
648 Log::getInstance()->log("VideoWin", Log::WARN , "Video Filter has no suitable output!");
649 videofilter->Release();
650 ReleaseMutex(filtermutex);
655 videofilter->Release();
669 int VideoWin::setAudioStreamType(UCHAR type)
672 if (!initted) return 0;
676 int VideoWin::dsplay()
678 if (!initted) return 0;
683 //So this is the real code, this prevents the feeder from calling noexisting objects!
684 WaitForSingleObject(filtermutex,INFINITE);
685 if (hres=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,
686 IID_IGraphBuilder,(void**)&dsgraphbuilder) != S_OK)
688 ReleaseMutex(filtermutex);
692 AddToRot(dsgraphbuilder,&graphidentifier);
696 if (aud_type==Audio::MP3) {
697 lastaudiomode=MPTYPE_MPEG_AUDIO_LAYER3;
699 lastaudiomode=MPTYPE_MPEG_AUDIO;
701 //lastaudiomode=MPTYPE_AC3;
702 sourcefilter=new DsSourceFilter(); //Creating our Source filter for pushing Data
704 if (hres=dsgraphbuilder->AddFilter(sourcefilter,L"Vomp Win Source Filter") != S_OK)
706 Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Vomp Source Filter!");
707 ReleaseMutex(filtermutex);
711 sourcefilter->GetAudioPin()->SetPinMode(lastaudiomode);
712 /*if (hres=dsgraphbuilder->Render((IPin*)sourcefilter->GetAudioPin()/*audio*)!=S_OK)
714 Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering audio!");
715 ReleaseMutex(filtermutex);
719 if (((AudioWin*)Audio::getInstance())->dsInitAudioFilter(dsgraphbuilder)==0)
721 Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering audio!");
722 ReleaseMutex(filtermutex);
728 if (dsInitVideoFilter()==0)
733 if (hres=CoCreateInstance(CLSID_SystemClock,NULL,CLSCTX_INPROC_SERVER,
734 IID_IReferenceClock,(void**)&dsrefclock)!=S_OK)
738 dsgraphbuilder->QueryInterface(IID_IMediaFilter,(void **) &dsmediafilter);
739 HRESULT hresdeb = dsmediafilter->SetSyncSource(dsrefclock);
741 dsgraphbuilder->QueryInterface(IID_IMediaControl,(void **) &dsmediacontrol);
742 dsgraphbuilder->QueryInterface(IID_IBasicAudio,(void **) &dsbasicaudio);
744 dsbasicaudio->put_Volume(audiovolume);
748 hresdeb=dsmediacontrol->Run();
749 iframemode=false;//exit iframe mode
750 ReleaseMutex(filtermutex);
754 int VideoWin::EnterIframePlayback()
756 if (!initted) return 0;
758 //So this is the real code, this prevents the feeder from calling noexisting objects!
759 WaitForSingleObject(filtermutex,INFINITE);
760 iframemode=true;//enter iframe mode
763 if (hres=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,
764 IID_IGraphBuilder,(void**)&dsgraphbuilder)!=S_OK) {
765 ReleaseMutex(filtermutex);
769 AddToRot(dsgraphbuilder,&graphidentifier);
772 //firstsynched=false;
773 sourcefilter=new DsSourceFilter(); //Creating our Source filter for pushing Data
775 if (hres=dsgraphbuilder->AddFilter(sourcefilter,L"Vomp Win Source Filter")!=S_OK) {
776 Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Vomp Source Filter!");
777 ReleaseMutex(filtermutex);
786 /* if (hres=CoCreateInstance(CLSID_SystemClock,NULL,CLSCTX_INPROC_SERVER,
787 IID_IReferenceClock,(void**)&dsrefclock)!=S_OK) {
791 dsgraphbuilder->QueryInterface(IID_IMediaFilter,(void **) &dsmediafilter);
792 dsmediafilter->SetSyncSource(/*dsrefclock*/NULL); //Run as fast as you can!
794 dsgraphbuilder->QueryInterface(IID_IMediaControl,(void **) &dsmediacontrol);
795 dsgraphbuilder->QueryInterface(IID_IBasicAudio,(void **) &dsbasicaudio);
799 dsmediacontrol->Run();
800 ReleaseMutex(filtermutex);
805 int VideoWin::dsstop()
807 if (!initted) return 0;
817 if (!initted) return 0;
823 int VideoWin::reset()
825 if (!initted) return 0;
831 int VideoWin::dsreset()
833 if (!initted) return 0;
836 iframemode=false;//exit iframe mode
842 int VideoWin::dspause()
844 if (!initted) return 0;
845 WaitForSingleObject(filtermutex,INFINITE);
846 if (dsmediacontrol) dsmediacontrol->Pause();
847 ReleaseMutex(filtermutex);
851 int VideoWin::pause()
853 if (!initted) return 0;
858 int VideoWin::unPause() // FIXME get rid - same as play!!
859 {//No on windows this is not the same, I don't get rid of!
860 if (!initted) return 0;
864 int VideoWin::dsunPause() // FIXME get rid - same as play!!
865 {//No on windows this is not the same, I don't get rid of!
866 if (!initted) return 0;
867 WaitForSingleObject(filtermutex,INFINITE);
868 if (dsmediacontrol) dsmediacontrol->Run();
869 ReleaseMutex(filtermutex);
874 int VideoWin::fastForward()
876 if (!initted) return 0;
881 int VideoWin::unFastForward()
883 if (!initted) return 0;
888 int VideoWin::attachFrameBuffer()
890 if (!initted) return 0;
894 int VideoWin::blank(void)
896 ((OsdWin*)Osd::getInstance())->Blank();
900 ULLONG VideoWin::getCurrentTimestamp()
902 REFERENCE_TIME startoffset;
903 REFERENCE_TIME ncr_time;
904 if (iframemode) return 0; //Not in iframe mode!
905 if (!dsrefclock || !sourcefilter) return 0;
907 sourcefilter->GetState(10,&state);
909 if (state==State_Running) dsrefclock->GetTime(&cr_time);
911 startoffset=sourcefilter->getStartOffset();
912 ncr_time-=startoffset;
913 ncr_time-=lastreftimeRT;
914 /* ULLONG result=frameNumberToTimecode(
915 VDR::getInstance()->frameNumberFromPosition(lastreftimeBYTE));*/
916 ULLONG result=lastreftimePTS;
917 result+=(ULLONG)(ncr_time/10000LL*90LL);
922 ULONG VideoWin::timecodeToFrameNumber(ULLONG timecode)
924 if (format == PAL) return (ULONG)(((double)timecode / (double)90000) * (double)25);
925 else return (ULONG)(((double)timecode / (double)90000) * (double)30);
928 ULLONG VideoWin::frameNumberToTimecode(ULONG framenumber)
930 if (format == PAL) return (ULLONG)(((double)framenumber * (double)90000) / (double)25);
931 else return (ULLONG)(((double)framenumber * (double)90000) / (double)30);
934 void VideoWin::CleanupDS()
936 WaitForSingleObject(filtermutex,INFINITE);
938 if (dsmediacontrol)dsmediacontrol->Stop();
939 if (cur_audio_media_sample) {
940 cur_audio_media_sample->Release();
941 cur_audio_media_sample=NULL;
943 if (cur_video_media_sample) {
944 cur_video_media_sample->Release();
945 cur_video_media_sample=NULL;
948 dsbasicaudio->Release();
951 if (dsvmrsurfnotify) {
952 dsvmrsurfnotify->Release();
953 dsvmrsurfnotify=NULL;
956 dsvmrrenderer->Release();
961 allocatorvmr->Release();
966 dsrefclock->Release();
970 dsmediafilter->Release();
976 if (dsmediacontrol) {
977 dsmediacontrol->Stop();
978 dsmediacontrol->Release();
983 RemoveFromRot(graphidentifier);
985 dsgraphbuilder->Release();
988 sourcefilter=NULL; //The Graph Builder destroys our SourceFilter
990 ReleaseMutex(filtermutex);
994 void VideoWin::PrepareMediaSample(const MediaPacketList& mplist,
997 mediapacket = mplist.front();
1000 UINT VideoWin::DeliverMediaSample(const UCHAR* buffer, UINT *samplepos)
1002 DeliverMediaPacket(mediapacket, buffer, samplepos);
1003 if (*samplepos == mediapacket.length) {
1010 UINT VideoWin::DeliverMediaPacket(MediaPacket packet,
1011 const UCHAR* buffer,
1015 /*First Check, if we have an audio sample*/
1016 if (!isdsinited()) return 0;
1019 *samplepos+=packet.length;
1020 MILLISLEEP(0); //yet not implemented//bad idea
1021 return packet.length;
1023 /*First Check, if we have an audio sample*/
1027 return 0; //Not in iframe mode!
1029 IMediaSample* ms=NULL;
1030 REFERENCE_TIME reftime1=0;
1031 REFERENCE_TIME reftime2=0;
1034 if (packet.disconti) {
1036 DeliverVideoMediaSample();
1039 /*Inspect PES-Header */
1041 if (*samplepos==0) {//stripheader
1042 headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/;
1043 *samplepos+=headerstrip;
1044 if ( packet.synched ) {
1045 DeliverVideoMediaSample();//write out old data
1046 /* if (packet.presentation_time<0) { //Preroll?
1047 *samplepos=packet.length;//if we have not processed at least one
1048 return packet.length;//synched packet ignore it!
1051 reftime1=packet.presentation_time;
1052 reftime2=reftime1+1;
1055 if (!firstsynched) {//
1056 *samplepos=packet.length;//if we have not processed at least one
1057 return packet.length;//synched packet ignore it!
1066 if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
1071 ms_pos=ms->GetActualDataLength();
1072 ms_length=ms->GetSize();
1073 haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);
1074 if ((ms_length-ms_pos)<1) {
1075 DeliverVideoMediaSample(); //we are full!
1076 if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
1081 ms_pos=ms->GetActualDataLength();
1082 ms_length=ms->GetSize();
1083 haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);
1085 ms->GetPointer(&ms_buf);
1088 if (ms_pos==0) {//will only be changed on first packet
1089 if (packet.disconti) {
1090 ms->SetDiscontinuity(TRUE);
1092 ms->SetDiscontinuity(FALSE);
1094 if (packet.synched) {
1095 ms->SetSyncPoint(TRUE);
1096 ms->SetTime(&reftime1,&reftime2);
1097 //ms->SetTime(NULL,NULL);
1098 ms->SetMediaTime(NULL, NULL);
1099 if (reftime1<0) ms->SetPreroll(TRUE);
1100 else ms->SetPreroll(FALSE);
1101 /*Timecode handling*/
1102 lastreftimeRT=reftime1;
1103 lastreftimePTS=packet.pts;
1106 ms->SetSyncPoint(FALSE);
1107 ms->SetTime(NULL,NULL);
1108 ms->SetMediaTime(NULL, NULL);
1109 ms->SetPreroll(FALSE);
1111 // ms->SetSyncPoint(TRUE);
1116 memcpy(ms_buf+ms_pos,buffer+packet.pos_buffer+*samplepos,haveToCopy);
1117 ms->SetActualDataLength(haveToCopy+ms_pos);
1119 *samplepos+=haveToCopy;
1121 return haveToCopy+headerstrip;
1125 *samplepos+=packet.length;
1126 MILLISLEEP(0); //yet not implemented//bad idea
1127 return packet.length;
1131 int VideoWin::getCurrentAudioMediaSample(IMediaSample** ms)
1133 //WaitForSingleObject(filtermutex,INFINITE);
1135 // ReleaseMutex(filtermutex);
1138 if (cur_audio_media_sample) {
1139 *ms=cur_audio_media_sample;//already open
1142 if (!sourcefilter->getCurrentAudioMediaSample(ms)) {
1143 // ReleaseMutex(filtermutex);
1145 if (*ms) (*ms)->SetActualDataLength(0);
1146 cur_audio_media_sample=*ms;
1147 //Don't release the mutex before deliver
1151 int VideoWin::getCurrentVideoMediaSample(IMediaSample** ms)
1153 //WaitForSingleObject(filtermutex,INFINITE);
1155 // ReleaseMutex(filtermutex);
1158 if (cur_video_media_sample) {
1159 *ms=cur_video_media_sample;//already open
1162 if (!sourcefilter->getCurrentVideoMediaSample(ms)) {
1163 // ReleaseMutex(filtermutex);
1165 if (*ms) (*ms)->SetActualDataLength(0);
1167 cur_video_media_sample=*ms;
1168 //Don't release the mutex before deliver
1172 int VideoWin::DeliverAudioMediaSample(){
1173 if (cur_audio_media_sample) {
1174 sourcefilter->DeliverAudioMediaSample(cur_audio_media_sample);
1175 cur_audio_media_sample=NULL;
1177 //ReleaseMutex(filtermutex);
1181 int VideoWin::DeliverVideoMediaSample(){
1182 if (cur_video_media_sample) {
1183 sourcefilter->DeliverVideoMediaSample(cur_video_media_sample);
1184 cur_video_media_sample=NULL;
1186 //ReleaseMutex(filtermutex);
1190 long long VideoWin::SetStartOffset(long long curreftime, bool *rsync)
1194 startoffset=curreftime;//offset is set for audio
1196 offsetvideonotset=false;
1200 if (offsetvideonotset) {
1201 offsetvideonotset=false;
1204 if ( (curreftime-lastrefvideotime)>10000000LL
1205 || (curreftime-lastrefvideotime)<-10000000LL) {//if pts jumps to big resync
1206 startoffset+=curreftime-lastrefvideotime;
1207 lastrefaudiotime+=curreftime-lastrefvideotime;
1209 offsetaudionotset=true;
1216 lastrefvideotime=curreftime;
1222 long long VideoWin::SetStartAudioOffset(long long curreftime, bool *rsync)
1226 startoffset=curreftime;
1228 offsetaudionotset=false;
1230 if (offsetaudionotset) {
1231 offsetaudionotset=false;
1234 if ( (curreftime-lastrefaudiotime)>10000000LL
1235 || (curreftime-lastrefaudiotime)<-10000000LL) {//if pts jumps to big resync
1236 startoffset+=curreftime-lastrefaudiotime;
1237 lastrefvideotime+=curreftime-lastrefaudiotime;
1239 offsetvideonotset=true;
1245 lastrefaudiotime=curreftime;
1249 void VideoWin::ResetTimeOffsets() {
1250 offsetnotset=true; //called from demuxer
1251 offsetvideonotset=true;
1252 offsetaudionotset=true;
1262 void VideoWin::SetAudioVolume(long volume)
1265 if (dsbasicaudio) dsbasicaudio->put_Volume(volume);
1268 void VideoWin::displayIFrame(const UCHAR* buffer, UINT length)
1270 if (!iframemode) EnterIframePlayback();
1272 if (!isdsinited()) return ;
1274 IMediaSample* ms=NULL;
1275 REFERENCE_TIME reftime1=0;
1276 REFERENCE_TIME reftime2=0;
1277 if (!videoon) return;
1279 if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
1285 ms->GetPointer(&ms_buf);
1286 ms_length=ms->GetSize();
1288 /*First Check, if we have an video sample*/
1289 DWORD read_pos = 0, write_pos = 0;
1290 DWORD pattern, packet_length;
1291 DWORD headerstrip=0;
1293 if (length < 4) return ;
1294 //Now we strip the pes header
1295 pattern = (buffer[0] << 16) | (buffer[1] << 8) | (buffer[2]);
1296 while (read_pos + 7 <= length)
1298 pattern = ((pattern << 8) & 0xFFFFFFFF) | buffer[read_pos+3];
1299 if (pattern < 0x000001E0 || pattern > 0x000001EF)
1303 headerstrip=buffer[read_pos+8]+9/*is this right*/;
1304 packet_length = ((buffer[read_pos+4] << 8) | (buffer[read_pos+5])) + 6;
1305 if (read_pos + packet_length > length)
1309 if ((write_pos+packet_length-headerstrip)>ms_length) {
1311 ms->SetSyncPoint(TRUE);
1312 ms->SetDiscontinuity(TRUE);
1314 } else ms->SetSyncPoint(FALSE);
1315 ms->SetTime(NULL,NULL);
1316 ms->SetMediaTime(NULL, NULL);
1317 ms->SetActualDataLength(write_pos);
1318 DeliverVideoMediaSample();
1320 if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
1325 ms_length=ms->GetSize();
1326 ms->GetPointer(&ms_buf);
1328 if (packet_length>headerstrip) {
1329 memcpy(ms_buf+write_pos, buffer+read_pos+headerstrip, packet_length-headerstrip);
1330 write_pos += packet_length-headerstrip;
1332 read_pos += packet_length;
1334 pattern = (buffer[read_pos] << 16) | (buffer[read_pos+1] << 8)
1335 | (buffer[read_pos+2]);
1340 if (first) {ms->SetSyncPoint(TRUE);first=false;}
1341 else ms->SetSyncPoint(FALSE);
1342 ms->SetTime(NULL,NULL);
1343 ms->SetMediaTime(NULL, NULL);
1344 ms->SetActualDataLength(write_pos);
1345 DeliverVideoMediaSample();
1349 // *samplepos+=packet.length;
1350 MILLISLEEP(0); //yet not implemented//bad idea
1355 bool VideoWin::supportsAc3(){
1356 if (sourcefilter != NULL) {
1357 return sourcefilter->supportsAc3();
1363 bool VideoWin::changeAType(int type,IMediaSample* ms){
1364 if (sourcefilter!= NULL) {
1366 return sourcefilter->changeAType(type,ms);
1375 int VideoWin::test()
1380 int VideoWin::test2()