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 "vtabsviewman.h"
29 #include "wwinvideofilter.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
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;
308 bool VideoWin::saveOptionstoServer()
310 VDR::getInstance()->configSave("DirectShow",
311 "VideoFilter",videofilterlist[videofilterselected].displayname);
315 IBaseFilter *VideoWin::getVideoFilter()
317 IBaseFilter *curfilter= NULL;
318 if (videofilterselected == -1)
321 for (i = 0;i <videofilterlist.size();i++)
324 if (videofilterlist[i].vmr9tested == true)
326 if (videofilterlist[i].vmr9 == true)
328 videofilterselected = i;
338 IMoniker * moni=NULL;
339 IBindCtx *bindctx=NULL;
340 if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
341 LPCOLESTR name=(LPCOLESTR)new WCHAR[strlen(videofilterlist[i].displayname)+1];
342 mbstowcs((wchar_t*)name,videofilterlist[i].displayname,strlen(videofilterlist[i].displayname)+1);
346 if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
348 if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
350 IAMDecoderCaps* desccaps=NULL;
351 if (curfilter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK)
354 desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps);
355 if (caps == DECODER_CAP_SUPPORTED)
357 videofilterlist[i].vmr9tested = true;
358 videofilterlist[i].vmr9 = true;
359 videofilterselected = i;
363 videofilterlist[i].vmr9tested = true;
364 videofilterlist[i].vmr9 = false;
366 curfilter->Release();
377 if (videofilterlist[i].vmr9) break;
380 if (curfilter != NULL)
382 VDR *vdr=VDR::getInstance();
385 vdr->configSave("DirectShow","VideoFilter",
386 videofilterlist[videofilterselected].displayname);
393 IBindCtx *bindctx=NULL;
394 if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
395 IMoniker * moni=NULL;
396 LPCOLESTR name=new WCHAR[strlen(videofilterlist[videofilterselected].displayname)+1];
397 mbstowcs((wchar_t*)name,videofilterlist[videofilterselected].displayname,
398 strlen(videofilterlist[videofilterselected].displayname)+1);
400 if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
402 if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
404 IAMDecoderCaps* desccaps=NULL;
405 if (curfilter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK)
408 desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps);
409 if (caps == DECODER_CAP_SUPPORTED)
411 videofilterlist[videofilterselected].vmr9tested = true;
412 videofilterlist[videofilterselected].vmr9 = true;
416 videofilterlist[videofilterselected].vmr9tested = true;
417 videofilterlist[videofilterselected].vmr9 = false;
418 Log::getInstance()->log("VideoWin", Log::WARN ,"Filter does not support VMR9, but is selected, manual selection!");
437 #ifdef DS_DEBUG // This stuff would not included in vomp due to lincemse restrcitions
438 #include "dshelper.h"
445 if (!initted) return 0;
449 bool VideoWin::addOptionPagesToWTB(WTabBar *wtb)
451 Boxx *box=new WWinVideoFilter();
452 wtb->addTab(tr("Video Filter"), box);
456 const VideoFilterDescList *VideoWin::getVideoFilterList(int &selected)
458 selected=videofilterselected;
459 return &videofilterlist;
462 bool VideoWin::selectVideoFilter(int filter)
464 IBindCtx *bindctx=NULL;
465 if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
466 IMoniker * moni=NULL;
467 LPCOLESTR name=new WCHAR[strlen(videofilterlist[filter].displayname)+1];
468 mbstowcs((wchar_t*)name,videofilterlist[filter].displayname,
469 strlen(videofilterlist[filter].displayname)+1);
472 if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
474 IBaseFilter* curfilter=NULL;
475 if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
477 IAMDecoderCaps* desccaps=NULL;
478 if (curfilter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK)
481 HRESULT hres=desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps);
482 if (caps == DECODER_CAP_SUPPORTED)
484 videofilterlist[filter].vmr9tested = true;
485 videofilterlist[filter].vmr9 = true;
490 videofilterlist[filter].vmr9tested = true;
491 videofilterlist[filter].vmr9 = false;
496 videofilterlist[filter].vmr9tested = true;
497 videofilterlist[filter].vmr9 = false;
501 curfilter->Release();
510 videofilterselected=filter;
520 int VideoWin::dsInitVideoFilter()
525 //We alloc the vmr9 as next step
526 if (hres=CoCreateInstance(CLSID_VideoMixingRenderer9,0,
527 CLSCTX_INPROC_SERVER,IID_IBaseFilter,(void**) &dsvmrrenderer)!=S_OK)
529 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed creating VMR9 renderer!");
530 ReleaseMutex(filtermutex);
534 if (hres=dsgraphbuilder->AddFilter(dsvmrrenderer,L"VMR9")!=S_OK)
536 ReleaseMutex(filtermutex);
538 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed adding VMR9 renderer!");
541 IVMRFilterConfig9* vmrfilconfig;
542 if (dsvmrrenderer->QueryInterface(IID_IVMRFilterConfig9,(void**)&vmrfilconfig)!=S_OK)
544 ReleaseMutex(filtermutex);
546 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Filterconfig interface!");
549 vmrfilconfig->SetRenderingMode(VMR9Mode_Renderless);
550 vmrfilconfig->Release();
552 if (dsvmrrenderer->QueryInterface(IID_IVMRSurfaceAllocatorNotify9,
553 (void**)& dsvmrsurfnotify) != S_OK)
555 ReleaseMutex(filtermutex);
557 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Surface Allocator interface!");
560 allocatorvmr=new DsAllocator();
561 dsvmrsurfnotify->AdviseSurfaceAllocator(NULL,allocatorvmr);
562 allocatorvmr->AdviseNotify(dsvmrsurfnotify);
564 IFilterGraph2*fg2=NULL;
565 if (dsgraphbuilder->QueryInterface(IID_IFilterGraph2,(void**)&fg2)!= S_OK)
567 Log::getInstance()->log("VideoWin", Log::WARN , "Failed querying for FilterGraph2 Interface!");
568 ReleaseMutex(filtermutex);
572 /*#ifndef NEW_DS_MECHANISMENS
574 if (hres=fg2->RenderEx((IPin*)sourcefilter->GetVideoPin()/*video*,
575 AM_RENDEREX_RENDERTOEXISTINGRENDERERS,NULL) != S_OK)
577 Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering Video!");
579 ReleaseMutex(filtermutex);
585 IBaseFilter*videofilter=getVideoFilter();
586 if (hres=dsgraphbuilder->AddFilter(videofilter,NULL) != S_OK)
588 Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Video Filter!");
589 ReleaseMutex(filtermutex);
593 IEnumPins *pinenum=NULL;
595 if (videofilter->EnumPins(&pinenum) == S_OK)
599 bool firststep=false;
601 while (pinenum->Next(1,¤t,&fetch)==S_OK)
604 if (current->QueryDirection(&dir)==S_OK)
606 if (dir == PINDIR_INPUT)
608 if (sourcefilter->GetVideoPin()->Connect(current,NULL)==S_OK)
618 if (firststep==false)
620 Log::getInstance()->log("VideoWin", Log::WARN , "Video Filter has no suitable input!");
621 videofilter->Release();
622 ReleaseMutex(filtermutex);
626 bool secondstep=false;
628 while (pinenum->Next(1,¤t,&fetch)==S_OK)
631 if (current->QueryDirection(&dir)==S_OK)
633 if (dir == PINDIR_OUTPUT)
636 if (fg2->RenderEx((IPin*)current/*video*/,
637 AM_RENDEREX_RENDERTOEXISTINGRENDERERS,NULL) ==S_OK)
647 if (secondstep==false)
649 Log::getInstance()->log("VideoWin", Log::WARN , "Video Filter has no suitable output!");
650 videofilter->Release();
651 ReleaseMutex(filtermutex);
656 videofilter->Release();
670 int VideoWin::setAudioStreamType(UCHAR type)
673 if (!initted) return 0;
677 int VideoWin::dsplay()
679 if (!initted) return 0;
684 //So this is the real code, this prevents the feeder from calling noexisting objects!
685 WaitForSingleObject(filtermutex,INFINITE);
686 if (hres=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,
687 IID_IGraphBuilder,(void**)&dsgraphbuilder) != S_OK)
689 ReleaseMutex(filtermutex);
693 AddToRot(dsgraphbuilder,&graphidentifier);
697 if (aud_type==Audio::MP3) {
698 lastaudiomode=MPTYPE_MPEG_AUDIO_LAYER3;
700 lastaudiomode=MPTYPE_MPEG_AUDIO;
702 //lastaudiomode=MPTYPE_AC3;
703 sourcefilter=new DsSourceFilter(); //Creating our Source filter for pushing Data
705 if (hres=dsgraphbuilder->AddFilter(sourcefilter,L"Vomp Win Source Filter") != S_OK)
707 Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Vomp Source Filter!");
708 ReleaseMutex(filtermutex);
712 sourcefilter->GetAudioPin()->SetPinMode(lastaudiomode);
713 /*if (hres=dsgraphbuilder->Render((IPin*)sourcefilter->GetAudioPin()/*audio*)!=S_OK)
715 Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering audio!");
716 ReleaseMutex(filtermutex);
720 if (((AudioWin*)Audio::getInstance())->dsInitAudioFilter(dsgraphbuilder)==0)
722 Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering audio!");
723 ReleaseMutex(filtermutex);
729 if (dsInitVideoFilter()==0)
734 if (hres=CoCreateInstance(CLSID_SystemClock,NULL,CLSCTX_INPROC_SERVER,
735 IID_IReferenceClock,(void**)&dsrefclock)!=S_OK)
739 dsgraphbuilder->QueryInterface(IID_IMediaFilter,(void **) &dsmediafilter);
740 HRESULT hresdeb = dsmediafilter->SetSyncSource(dsrefclock);
742 dsgraphbuilder->QueryInterface(IID_IMediaControl,(void **) &dsmediacontrol);
743 dsgraphbuilder->QueryInterface(IID_IBasicAudio,(void **) &dsbasicaudio);
745 dsbasicaudio->put_Volume(audiovolume);
749 hresdeb=dsmediacontrol->Run();
750 iframemode=false;//exit iframe mode
751 ReleaseMutex(filtermutex);
755 int VideoWin::EnterIframePlayback()
757 if (!initted) return 0;
759 //So this is the real code, this prevents the feeder from calling noexisting objects!
760 WaitForSingleObject(filtermutex,INFINITE);
761 iframemode=true;//enter iframe mode
764 if (hres=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,
765 IID_IGraphBuilder,(void**)&dsgraphbuilder)!=S_OK) {
766 ReleaseMutex(filtermutex);
770 AddToRot(dsgraphbuilder,&graphidentifier);
773 //firstsynched=false;
774 sourcefilter=new DsSourceFilter(); //Creating our Source filter for pushing Data
776 if (hres=dsgraphbuilder->AddFilter(sourcefilter,L"Vomp Win Source Filter")!=S_OK) {
777 Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Vomp Source Filter!");
778 ReleaseMutex(filtermutex);
787 /* if (hres=CoCreateInstance(CLSID_SystemClock,NULL,CLSCTX_INPROC_SERVER,
788 IID_IReferenceClock,(void**)&dsrefclock)!=S_OK) {
792 dsgraphbuilder->QueryInterface(IID_IMediaFilter,(void **) &dsmediafilter);
793 dsmediafilter->SetSyncSource(/*dsrefclock*/NULL); //Run as fast as you can!
795 dsgraphbuilder->QueryInterface(IID_IMediaControl,(void **) &dsmediacontrol);
796 dsgraphbuilder->QueryInterface(IID_IBasicAudio,(void **) &dsbasicaudio);
800 dsmediacontrol->Run();
801 ReleaseMutex(filtermutex);
806 int VideoWin::dsstop()
808 if (!initted) return 0;
818 if (!initted) return 0;
824 int VideoWin::reset()
826 if (!initted) return 0;
832 int VideoWin::dsreset()
834 if (!initted) return 0;
837 iframemode=false;//exit iframe mode
843 int VideoWin::dspause()
845 if (!initted) return 0;
846 WaitForSingleObject(filtermutex,INFINITE);
847 if (dsmediacontrol) dsmediacontrol->Pause();
848 ReleaseMutex(filtermutex);
852 int VideoWin::pause()
854 if (!initted) return 0;
859 int VideoWin::unPause() // FIXME get rid - same as play!!
860 {//No on windows this is not the same, I don't get rid of!
861 if (!initted) return 0;
865 int VideoWin::dsunPause() // FIXME get rid - same as play!!
866 {//No on windows this is not the same, I don't get rid of!
867 if (!initted) return 0;
868 WaitForSingleObject(filtermutex,INFINITE);
869 if (dsmediacontrol) dsmediacontrol->Run();
870 ReleaseMutex(filtermutex);
875 int VideoWin::fastForward()
877 if (!initted) return 0;
882 int VideoWin::unFastForward()
884 if (!initted) return 0;
889 int VideoWin::attachFrameBuffer()
891 if (!initted) return 0;
895 int VideoWin::blank(void)
897 ((OsdWin*)Osd::getInstance())->Blank();
901 ULLONG VideoWin::getCurrentTimestamp()
903 REFERENCE_TIME startoffset;
904 REFERENCE_TIME ncr_time;
905 if (iframemode) return 0; //Not in iframe mode!
906 if (!dsrefclock || !sourcefilter) return 0;
908 sourcefilter->GetState(10,&state);
910 if (state==State_Running) dsrefclock->GetTime(&cr_time);
912 startoffset=sourcefilter->getStartOffset();
913 ncr_time-=startoffset;
914 ncr_time-=lastreftimeRT;
915 /* ULLONG result=frameNumberToTimecode(
916 VDR::getInstance()->frameNumberFromPosition(lastreftimeBYTE));*/
917 ULLONG result=lastreftimePTS;
918 result+=(ULLONG)(ncr_time/10000LL*90LL);
923 ULONG VideoWin::timecodeToFrameNumber(ULLONG timecode)
925 if (format == PAL) return (ULONG)(((double)timecode / (double)90000) * (double)25);
926 else return (ULONG)(((double)timecode / (double)90000) * (double)30);
929 ULLONG VideoWin::frameNumberToTimecode(ULONG framenumber)
931 if (format == PAL) return (ULLONG)(((double)framenumber * (double)90000) / (double)25);
932 else return (ULLONG)(((double)framenumber * (double)90000) / (double)30);
935 void VideoWin::CleanupDS()
937 WaitForSingleObject(filtermutex,INFINITE);
939 if (dsmediacontrol)dsmediacontrol->Stop();
940 if (cur_audio_media_sample) {
941 cur_audio_media_sample->Release();
942 cur_audio_media_sample=NULL;
944 if (cur_video_media_sample) {
945 cur_video_media_sample->Release();
946 cur_video_media_sample=NULL;
949 dsbasicaudio->Release();
952 if (dsvmrsurfnotify) {
953 dsvmrsurfnotify->Release();
954 dsvmrsurfnotify=NULL;
957 dsvmrrenderer->Release();
962 allocatorvmr->Release();
967 dsrefclock->Release();
971 dsmediafilter->Release();
977 if (dsmediacontrol) {
978 dsmediacontrol->Stop();
979 dsmediacontrol->Release();
984 RemoveFromRot(graphidentifier);
986 dsgraphbuilder->Release();
989 sourcefilter=NULL; //The Graph Builder destroys our SourceFilter
991 ReleaseMutex(filtermutex);
995 void VideoWin::PrepareMediaSample(const MediaPacketList& mplist,
998 mediapacket = mplist.front();
1001 UINT VideoWin::DeliverMediaSample(const UCHAR* buffer, UINT *samplepos)
1003 DeliverMediaPacket(mediapacket, buffer, samplepos);
1004 if (*samplepos == mediapacket.length) {
1011 UINT VideoWin::DeliverMediaPacket(MediaPacket packet,
1012 const UCHAR* buffer,
1016 /*First Check, if we have an audio sample*/
1017 if (!isdsinited()) return 0;
1020 *samplepos+=packet.length;
1021 MILLISLEEP(0); //yet not implemented//bad idea
1022 return packet.length;
1024 /*First Check, if we have an audio sample*/
1028 return 0; //Not in iframe mode!
1030 IMediaSample* ms=NULL;
1031 REFERENCE_TIME reftime1=0;
1032 REFERENCE_TIME reftime2=0;
1035 if (packet.disconti) {
1037 DeliverVideoMediaSample();
1040 /*Inspect PES-Header */
1042 if (*samplepos==0) {//stripheader
1043 headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/;
1044 *samplepos+=headerstrip;
1045 if ( packet.synched ) {
1046 DeliverVideoMediaSample();//write out old data
1047 /* if (packet.presentation_time<0) { //Preroll?
1048 *samplepos=packet.length;//if we have not processed at least one
1049 return packet.length;//synched packet ignore it!
1052 reftime1=packet.presentation_time;
1053 reftime2=reftime1+1;
1056 if (!firstsynched) {//
1057 *samplepos=packet.length;//if we have not processed at least one
1058 return packet.length;//synched packet ignore it!
1067 if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
1072 ms_pos=ms->GetActualDataLength();
1073 ms_length=ms->GetSize();
1074 haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);
1075 if ((ms_length-ms_pos)<1) {
1076 DeliverVideoMediaSample(); //we are full!
1077 if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
1082 ms_pos=ms->GetActualDataLength();
1083 ms_length=ms->GetSize();
1084 haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);
1086 ms->GetPointer(&ms_buf);
1089 if (ms_pos==0) {//will only be changed on first packet
1090 if (packet.disconti) {
1091 ms->SetDiscontinuity(TRUE);
1093 ms->SetDiscontinuity(FALSE);
1095 if (packet.synched) {
1096 ms->SetSyncPoint(TRUE);
1097 ms->SetTime(&reftime1,&reftime2);
1098 //ms->SetTime(NULL,NULL);
1099 ms->SetMediaTime(NULL, NULL);
1100 if (reftime1<0) ms->SetPreroll(TRUE);
1101 else ms->SetPreroll(FALSE);
1102 /*Timecode handling*/
1103 lastreftimeRT=reftime1;
1104 lastreftimePTS=packet.pts;
1107 ms->SetSyncPoint(FALSE);
1108 ms->SetTime(NULL,NULL);
1109 ms->SetMediaTime(NULL, NULL);
1110 ms->SetPreroll(FALSE);
1112 // ms->SetSyncPoint(TRUE);
1117 memcpy(ms_buf+ms_pos,buffer+packet.pos_buffer+*samplepos,haveToCopy);
1118 ms->SetActualDataLength(haveToCopy+ms_pos);
1120 *samplepos+=haveToCopy;
1122 return haveToCopy+headerstrip;
1126 *samplepos+=packet.length;
1127 MILLISLEEP(0); //yet not implemented//bad idea
1128 return packet.length;
1132 int VideoWin::getCurrentAudioMediaSample(IMediaSample** ms)
1134 //WaitForSingleObject(filtermutex,INFINITE);
1136 // ReleaseMutex(filtermutex);
1139 if (cur_audio_media_sample) {
1140 *ms=cur_audio_media_sample;//already open
1143 if (!sourcefilter->getCurrentAudioMediaSample(ms)) {
1144 // ReleaseMutex(filtermutex);
1146 if (*ms) (*ms)->SetActualDataLength(0);
1147 cur_audio_media_sample=*ms;
1148 //Don't release the mutex before deliver
1152 int VideoWin::getCurrentVideoMediaSample(IMediaSample** ms)
1154 //WaitForSingleObject(filtermutex,INFINITE);
1156 // ReleaseMutex(filtermutex);
1159 if (cur_video_media_sample) {
1160 *ms=cur_video_media_sample;//already open
1163 if (!sourcefilter->getCurrentVideoMediaSample(ms)) {
1164 // ReleaseMutex(filtermutex);
1166 if (*ms) (*ms)->SetActualDataLength(0);
1168 cur_video_media_sample=*ms;
1169 //Don't release the mutex before deliver
1173 int VideoWin::DeliverAudioMediaSample(){
1174 if (cur_audio_media_sample) {
1175 sourcefilter->DeliverAudioMediaSample(cur_audio_media_sample);
1176 cur_audio_media_sample=NULL;
1178 //ReleaseMutex(filtermutex);
1182 int VideoWin::DeliverVideoMediaSample(){
1183 if (cur_video_media_sample) {
1184 sourcefilter->DeliverVideoMediaSample(cur_video_media_sample);
1185 cur_video_media_sample=NULL;
1187 //ReleaseMutex(filtermutex);
1191 long long VideoWin::SetStartOffset(long long curreftime, bool *rsync)
1195 startoffset=curreftime;//offset is set for audio
1197 offsetvideonotset=false;
1201 if (offsetvideonotset) {
1202 offsetvideonotset=false;
1205 if ( (curreftime-lastrefvideotime)>10000000LL
1206 || (curreftime-lastrefvideotime)<-10000000LL) {//if pts jumps to big resync
1207 startoffset+=curreftime-lastrefvideotime;
1208 lastrefaudiotime+=curreftime-lastrefvideotime;
1210 offsetaudionotset=true;
1217 lastrefvideotime=curreftime;
1223 long long VideoWin::SetStartAudioOffset(long long curreftime, bool *rsync)
1227 startoffset=curreftime;
1229 offsetaudionotset=false;
1231 if (offsetaudionotset) {
1232 offsetaudionotset=false;
1235 if ( (curreftime-lastrefaudiotime)>10000000LL
1236 || (curreftime-lastrefaudiotime)<-10000000LL) {//if pts jumps to big resync
1237 startoffset+=curreftime-lastrefaudiotime;
1238 lastrefvideotime+=curreftime-lastrefaudiotime;
1240 offsetvideonotset=true;
1246 lastrefaudiotime=curreftime;
1250 void VideoWin::ResetTimeOffsets() {
1251 offsetnotset=true; //called from demuxer
1252 offsetvideonotset=true;
1253 offsetaudionotset=true;
1263 void VideoWin::SetAudioVolume(long volume)
1266 if (dsbasicaudio) dsbasicaudio->put_Volume(volume);
1269 void VideoWin::displayIFrame(const UCHAR* buffer, UINT length)
1271 if (!iframemode) EnterIframePlayback();
1273 if (!isdsinited()) return ;
1275 IMediaSample* ms=NULL;
1276 REFERENCE_TIME reftime1=0;
1277 REFERENCE_TIME reftime2=0;
1278 if (!videoon) return;
1280 if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
1286 ms->GetPointer(&ms_buf);
1287 ms_length=ms->GetSize();
1289 /*First Check, if we have an video sample*/
1290 DWORD read_pos = 0, write_pos = 0;
1291 DWORD pattern, packet_length;
1292 DWORD headerstrip=0;
1294 if (length < 4) return ;
1295 //Now we strip the pes header
1296 pattern = (buffer[0] << 16) | (buffer[1] << 8) | (buffer[2]);
1297 while (read_pos + 7 <= length)
1299 pattern = ((pattern << 8) & 0xFFFFFFFF) | buffer[read_pos+3];
1300 if (pattern < 0x000001E0 || pattern > 0x000001EF)
1304 headerstrip=buffer[read_pos+8]+9/*is this right*/;
1305 packet_length = ((buffer[read_pos+4] << 8) | (buffer[read_pos+5])) + 6;
1306 if (read_pos + packet_length > length)
1310 if ((write_pos+packet_length-headerstrip)>ms_length) {
1312 ms->SetSyncPoint(TRUE);
1313 ms->SetDiscontinuity(TRUE);
1315 } else ms->SetSyncPoint(FALSE);
1316 ms->SetTime(NULL,NULL);
1317 ms->SetMediaTime(NULL, NULL);
1318 ms->SetActualDataLength(write_pos);
1319 DeliverVideoMediaSample();
1321 if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
1326 ms_length=ms->GetSize();
1327 ms->GetPointer(&ms_buf);
1329 if (packet_length>headerstrip) {
1330 memcpy(ms_buf+write_pos, buffer+read_pos+headerstrip, packet_length-headerstrip);
1331 write_pos += packet_length-headerstrip;
1333 read_pos += packet_length;
1335 pattern = (buffer[read_pos] << 16) | (buffer[read_pos+1] << 8)
1336 | (buffer[read_pos+2]);
1341 if (first) {ms->SetSyncPoint(TRUE);first=false;}
1342 else ms->SetSyncPoint(FALSE);
1343 ms->SetTime(NULL,NULL);
1344 ms->SetMediaTime(NULL, NULL);
1345 ms->SetActualDataLength(write_pos);
1346 DeliverVideoMediaSample();
1350 // *samplepos+=packet.length;
1351 MILLISLEEP(0); //yet not implemented//bad idea
1356 bool VideoWin::supportsAc3(){
1357 if (sourcefilter != NULL) {
1358 return sourcefilter->supportsAc3();
1364 bool VideoWin::changeAType(int type,IMediaSample* ms){
1365 if (sourcefilter!= NULL) {
1367 return sourcefilter->changeAType(type,ms);
1376 int VideoWin::test()
1381 int VideoWin::test2()