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 if (videofilterselected!=-1) {
310 VDR::getInstance()->configSave("DirectShow",
311 "VideoFilter",videofilterlist[videofilterselected].displayname);
316 IBaseFilter *VideoWin::getVideoFilter()
318 IBaseFilter *curfilter= NULL;
319 if (videofilterselected == -1)
322 for (i = 0;i <videofilterlist.size();i++)
325 if (videofilterlist[i].vmr9tested == true)
327 if (videofilterlist[i].vmr9 == true)
329 videofilterselected = i;
339 IMoniker * moni=NULL;
340 IBindCtx *bindctx=NULL;
341 if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
342 LPCOLESTR name=(LPCOLESTR)new WCHAR[strlen(videofilterlist[i].displayname)+1];
343 mbstowcs((wchar_t*)name,videofilterlist[i].displayname,strlen(videofilterlist[i].displayname)+1);
347 if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
349 if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
351 IAMDecoderCaps* desccaps=NULL;
352 if (curfilter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK)
355 desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps);
356 if (caps == DECODER_CAP_SUPPORTED)
358 videofilterlist[i].vmr9tested = true;
359 videofilterlist[i].vmr9 = true;
360 videofilterselected = i;
364 videofilterlist[i].vmr9tested = true;
365 videofilterlist[i].vmr9 = false;
367 curfilter->Release();
378 if (videofilterlist[i].vmr9) break;
381 if (curfilter != NULL)
383 VDR *vdr=VDR::getInstance();
386 vdr->configSave("DirectShow","VideoFilter",
387 videofilterlist[videofilterselected].displayname);
394 IBindCtx *bindctx=NULL;
395 if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
396 IMoniker * moni=NULL;
397 LPCOLESTR name=new WCHAR[strlen(videofilterlist[videofilterselected].displayname)+1];
398 mbstowcs((wchar_t*)name,videofilterlist[videofilterselected].displayname,
399 strlen(videofilterlist[videofilterselected].displayname)+1);
401 if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
403 if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
405 IAMDecoderCaps* desccaps=NULL;
406 if (curfilter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK)
409 desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps);
410 if (caps == DECODER_CAP_SUPPORTED)
412 videofilterlist[videofilterselected].vmr9tested = true;
413 videofilterlist[videofilterselected].vmr9 = true;
417 videofilterlist[videofilterselected].vmr9tested = true;
418 videofilterlist[videofilterselected].vmr9 = false;
419 Log::getInstance()->log("VideoWin", Log::WARN ,"Filter does not support VMR9, but is selected, manual selection!");
438 #ifdef DS_DEBUG // This stuff would not included in vomp due to lincemse restrcitions
439 #include "dshelper.h"
446 if (!initted) return 0;
450 bool VideoWin::addOptionPagesToWTB(WTabBar *wtb)
452 Boxx *box=new WWinVideoFilter();
453 wtb->addTab(tr("Video Filter"), box);
457 const VideoFilterDescList *VideoWin::getVideoFilterList(int &selected)
459 selected=videofilterselected;
460 return &videofilterlist;
463 bool VideoWin::selectVideoFilter(int filter)
465 IBindCtx *bindctx=NULL;
466 if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
467 IMoniker * moni=NULL;
468 LPCOLESTR name=new WCHAR[strlen(videofilterlist[filter].displayname)+1];
469 mbstowcs((wchar_t*)name,videofilterlist[filter].displayname,
470 strlen(videofilterlist[filter].displayname)+1);
473 if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
475 IBaseFilter* curfilter=NULL;
476 if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
478 IAMDecoderCaps* desccaps=NULL;
479 if (curfilter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK)
482 HRESULT hres=desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps);
483 if (caps == DECODER_CAP_SUPPORTED)
485 videofilterlist[filter].vmr9tested = true;
486 videofilterlist[filter].vmr9 = true;
491 videofilterlist[filter].vmr9tested = true;
492 videofilterlist[filter].vmr9 = false;
497 videofilterlist[filter].vmr9tested = true;
498 videofilterlist[filter].vmr9 = false;
502 curfilter->Release();
511 videofilterselected=filter;
521 int VideoWin::dsInitVideoFilter()
526 //We alloc the vmr9 as next step
527 if (hres=CoCreateInstance(CLSID_VideoMixingRenderer9,0,
528 CLSCTX_INPROC_SERVER,IID_IBaseFilter,(void**) &dsvmrrenderer)!=S_OK)
530 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed creating VMR9 renderer!");
531 ReleaseMutex(filtermutex);
535 if (hres=dsgraphbuilder->AddFilter(dsvmrrenderer,L"VMR9")!=S_OK)
537 ReleaseMutex(filtermutex);
539 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed adding VMR9 renderer!");
542 IVMRFilterConfig9* vmrfilconfig;
543 if (dsvmrrenderer->QueryInterface(IID_IVMRFilterConfig9,(void**)&vmrfilconfig)!=S_OK)
545 ReleaseMutex(filtermutex);
547 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Filterconfig interface!");
550 vmrfilconfig->SetRenderingMode(VMR9Mode_Renderless);
551 vmrfilconfig->Release();
553 if (dsvmrrenderer->QueryInterface(IID_IVMRSurfaceAllocatorNotify9,
554 (void**)& dsvmrsurfnotify) != S_OK)
556 ReleaseMutex(filtermutex);
558 Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Surface Allocator interface!");
561 allocatorvmr=new DsAllocator();
562 dsvmrsurfnotify->AdviseSurfaceAllocator(NULL,allocatorvmr);
563 allocatorvmr->AdviseNotify(dsvmrsurfnotify);
565 IFilterGraph2*fg2=NULL;
566 if (dsgraphbuilder->QueryInterface(IID_IFilterGraph2,(void**)&fg2)!= S_OK)
568 Log::getInstance()->log("VideoWin", Log::WARN , "Failed querying for FilterGraph2 Interface!");
569 ReleaseMutex(filtermutex);
573 /*#ifndef NEW_DS_MECHANISMENS
575 if (hres=fg2->RenderEx((IPin*)sourcefilter->GetVideoPin()/*video*,
576 AM_RENDEREX_RENDERTOEXISTINGRENDERERS,NULL) != S_OK)
578 Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering Video!");
580 ReleaseMutex(filtermutex);
586 IBaseFilter*videofilter=getVideoFilter();
587 if (hres=dsgraphbuilder->AddFilter(videofilter,NULL) != S_OK)
589 Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Video Filter!");
590 ReleaseMutex(filtermutex);
594 IEnumPins *pinenum=NULL;
596 if (videofilter->EnumPins(&pinenum) == S_OK)
600 bool firststep=false;
602 while (pinenum->Next(1,¤t,&fetch)==S_OK)
605 if (current->QueryDirection(&dir)==S_OK)
607 if (dir == PINDIR_INPUT)
609 if (sourcefilter->GetVideoPin()->Connect(current,NULL)==S_OK)
619 if (firststep==false)
621 Log::getInstance()->log("VideoWin", Log::WARN , "Video Filter has no suitable input!");
622 videofilter->Release();
623 ReleaseMutex(filtermutex);
627 bool secondstep=false;
629 while (pinenum->Next(1,¤t,&fetch)==S_OK)
632 if (current->QueryDirection(&dir)==S_OK)
634 if (dir == PINDIR_OUTPUT)
637 if (fg2->RenderEx((IPin*)current/*video*/,
638 AM_RENDEREX_RENDERTOEXISTINGRENDERERS,NULL) ==S_OK)
648 if (secondstep==false)
650 Log::getInstance()->log("VideoWin", Log::WARN , "Video Filter has no suitable output!");
651 videofilter->Release();
652 ReleaseMutex(filtermutex);
657 videofilter->Release();
671 int VideoWin::setAudioStreamType(UCHAR type)
674 if (!initted) return 0;
678 int VideoWin::dsplay()
680 if (!initted) return 0;
685 //So this is the real code, this prevents the feeder from calling noexisting objects!
686 WaitForSingleObject(filtermutex,INFINITE);
687 if (hres=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,
688 IID_IGraphBuilder,(void**)&dsgraphbuilder) != S_OK)
690 ReleaseMutex(filtermutex);
694 AddToRot(dsgraphbuilder,&graphidentifier);
698 if (aud_type==Audio::MP3) {
699 lastaudiomode=MPTYPE_MPEG_AUDIO_LAYER3;
701 lastaudiomode=MPTYPE_MPEG_AUDIO;
703 //lastaudiomode=MPTYPE_AC3;
704 sourcefilter=new DsSourceFilter(); //Creating our Source filter for pushing Data
706 if (hres=dsgraphbuilder->AddFilter(sourcefilter,L"Vomp Win Source Filter") != S_OK)
708 Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Vomp Source Filter!");
709 ReleaseMutex(filtermutex);
713 sourcefilter->GetAudioPin()->SetPinMode(lastaudiomode);
714 /*if (hres=dsgraphbuilder->Render((IPin*)sourcefilter->GetAudioPin()/*audio*)!=S_OK)
716 Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering audio!");
717 ReleaseMutex(filtermutex);
721 if (((AudioWin*)Audio::getInstance())->dsInitAudioFilter(dsgraphbuilder)==0)
723 Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering audio!");
724 ReleaseMutex(filtermutex);
730 if (dsInitVideoFilter()==0)
735 if (hres=CoCreateInstance(CLSID_SystemClock,NULL,CLSCTX_INPROC_SERVER,
736 IID_IReferenceClock,(void**)&dsrefclock)!=S_OK)
740 dsgraphbuilder->QueryInterface(IID_IMediaFilter,(void **) &dsmediafilter);
741 HRESULT hresdeb = dsmediafilter->SetSyncSource(dsrefclock);
743 dsgraphbuilder->QueryInterface(IID_IMediaControl,(void **) &dsmediacontrol);
744 dsgraphbuilder->QueryInterface(IID_IBasicAudio,(void **) &dsbasicaudio);
746 dsbasicaudio->put_Volume(audiovolume);
750 hresdeb=dsmediacontrol->Run();
751 iframemode=false;//exit iframe mode
752 ReleaseMutex(filtermutex);
756 int VideoWin::EnterIframePlayback()
758 if (!initted) return 0;
760 //So this is the real code, this prevents the feeder from calling noexisting objects!
761 WaitForSingleObject(filtermutex,INFINITE);
762 iframemode=true;//enter iframe mode
765 if (hres=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,
766 IID_IGraphBuilder,(void**)&dsgraphbuilder)!=S_OK) {
767 ReleaseMutex(filtermutex);
771 AddToRot(dsgraphbuilder,&graphidentifier);
774 //firstsynched=false;
775 sourcefilter=new DsSourceFilter(); //Creating our Source filter for pushing Data
777 if (hres=dsgraphbuilder->AddFilter(sourcefilter,L"Vomp Win Source Filter")!=S_OK) {
778 Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Vomp Source Filter!");
779 ReleaseMutex(filtermutex);
788 /* if (hres=CoCreateInstance(CLSID_SystemClock,NULL,CLSCTX_INPROC_SERVER,
789 IID_IReferenceClock,(void**)&dsrefclock)!=S_OK) {
793 dsgraphbuilder->QueryInterface(IID_IMediaFilter,(void **) &dsmediafilter);
794 dsmediafilter->SetSyncSource(/*dsrefclock*/NULL); //Run as fast as you can!
796 dsgraphbuilder->QueryInterface(IID_IMediaControl,(void **) &dsmediacontrol);
797 dsgraphbuilder->QueryInterface(IID_IBasicAudio,(void **) &dsbasicaudio);
801 dsmediacontrol->Run();
802 ReleaseMutex(filtermutex);
807 int VideoWin::dsstop()
809 if (!initted) return 0;
819 if (!initted) return 0;
825 int VideoWin::reset()
827 if (!initted) return 0;
833 int VideoWin::dsreset()
835 if (!initted) return 0;
838 iframemode=false;//exit iframe mode
844 int VideoWin::dspause()
846 if (!initted) return 0;
847 WaitForSingleObject(filtermutex,INFINITE);
848 if (dsmediacontrol) dsmediacontrol->Pause();
849 ReleaseMutex(filtermutex);
853 int VideoWin::pause()
855 if (!initted) return 0;
860 int VideoWin::unPause() // FIXME get rid - same as play!!
861 {//No on windows this is not the same, I don't get rid of!
862 if (!initted) return 0;
866 int VideoWin::dsunPause() // FIXME get rid - same as play!!
867 {//No on windows this is not the same, I don't get rid of!
868 if (!initted) return 0;
869 WaitForSingleObject(filtermutex,INFINITE);
870 if (dsmediacontrol) dsmediacontrol->Run();
871 ReleaseMutex(filtermutex);
876 int VideoWin::fastForward()
878 if (!initted) return 0;
883 int VideoWin::unFastForward()
885 if (!initted) return 0;
890 int VideoWin::attachFrameBuffer()
892 if (!initted) return 0;
896 int VideoWin::blank(void)
898 ((OsdWin*)Osd::getInstance())->Blank();
902 ULLONG VideoWin::getCurrentTimestamp()
904 REFERENCE_TIME startoffset;
905 REFERENCE_TIME ncr_time;
906 if (iframemode) return 0; //Not in iframe mode!
907 if (!dsrefclock || !sourcefilter) return 0;
909 sourcefilter->GetState(10,&state);
911 if (state==State_Running) dsrefclock->GetTime(&cr_time);
913 startoffset=sourcefilter->getStartOffset();
914 ncr_time-=startoffset;
915 ncr_time-=lastreftimeRT;
916 /* ULLONG result=frameNumberToTimecode(
917 VDR::getInstance()->frameNumberFromPosition(lastreftimeBYTE));*/
918 ULLONG result=lastreftimePTS;
919 result+=(ULLONG)(ncr_time/10000LL*90LL);
924 ULONG VideoWin::timecodeToFrameNumber(ULLONG timecode)
926 if (format == PAL) return (ULONG)(((double)timecode / (double)90000) * (double)25);
927 else return (ULONG)(((double)timecode / (double)90000) * (double)30);
930 ULLONG VideoWin::frameNumberToTimecode(ULONG framenumber)
932 if (format == PAL) return (ULLONG)(((double)framenumber * (double)90000) / (double)25);
933 else return (ULLONG)(((double)framenumber * (double)90000) / (double)30);
936 void VideoWin::CleanupDS()
938 WaitForSingleObject(filtermutex,INFINITE);
940 if (dsmediacontrol)dsmediacontrol->Stop();
941 if (cur_audio_media_sample) {
942 cur_audio_media_sample->Release();
943 cur_audio_media_sample=NULL;
945 if (cur_video_media_sample) {
946 cur_video_media_sample->Release();
947 cur_video_media_sample=NULL;
950 dsbasicaudio->Release();
953 if (dsvmrsurfnotify) {
954 dsvmrsurfnotify->Release();
955 dsvmrsurfnotify=NULL;
958 dsvmrrenderer->Release();
963 allocatorvmr->Release();
968 dsrefclock->Release();
972 dsmediafilter->Release();
978 if (dsmediacontrol) {
979 dsmediacontrol->Stop();
980 dsmediacontrol->Release();
985 RemoveFromRot(graphidentifier);
987 dsgraphbuilder->Release();
990 sourcefilter=NULL; //The Graph Builder destroys our SourceFilter
992 ReleaseMutex(filtermutex);
996 void VideoWin::PrepareMediaSample(const MediaPacketList& mplist,
999 mediapacket = mplist.front();
1002 UINT VideoWin::DeliverMediaSample(const UCHAR* buffer, UINT *samplepos)
1004 DeliverMediaPacket(mediapacket, buffer, samplepos);
1005 if (*samplepos == mediapacket.length) {
1012 UINT VideoWin::DeliverMediaPacket(MediaPacket packet,
1013 const UCHAR* buffer,
1017 /*First Check, if we have an audio sample*/
1018 if (!isdsinited()) return 0;
1021 *samplepos+=packet.length;
1022 MILLISLEEP(0); //yet not implemented//bad idea
1023 return packet.length;
1025 /*First Check, if we have an audio sample*/
1029 return 0; //Not in iframe mode!
1031 IMediaSample* ms=NULL;
1032 REFERENCE_TIME reftime1=0;
1033 REFERENCE_TIME reftime2=0;
1036 if (packet.disconti) {
1038 DeliverVideoMediaSample();
1041 /*Inspect PES-Header */
1043 if (*samplepos==0) {//stripheader
1044 headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/;
1045 *samplepos+=headerstrip;
1046 if ( packet.synched ) {
1047 DeliverVideoMediaSample();//write out old data
1048 /* if (packet.presentation_time<0) { //Preroll?
1049 *samplepos=packet.length;//if we have not processed at least one
1050 return packet.length;//synched packet ignore it!
1053 reftime1=packet.presentation_time;
1054 reftime2=reftime1+1;
1057 if (!firstsynched) {//
1058 *samplepos=packet.length;//if we have not processed at least one
1059 return packet.length;//synched packet ignore it!
1068 if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
1073 ms_pos=ms->GetActualDataLength();
1074 ms_length=ms->GetSize();
1075 haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);
1076 if ((ms_length-ms_pos)<1) {
1077 DeliverVideoMediaSample(); //we are full!
1078 if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
1083 ms_pos=ms->GetActualDataLength();
1084 ms_length=ms->GetSize();
1085 haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);
1087 ms->GetPointer(&ms_buf);
1090 if (ms_pos==0) {//will only be changed on first packet
1091 if (packet.disconti) {
1092 ms->SetDiscontinuity(TRUE);
1094 ms->SetDiscontinuity(FALSE);
1096 if (packet.synched) {
1097 ms->SetSyncPoint(TRUE);
1098 ms->SetTime(&reftime1,&reftime2);
1099 //ms->SetTime(NULL,NULL);
1100 ms->SetMediaTime(NULL, NULL);
1101 if (reftime1<0) ms->SetPreroll(TRUE);
1102 else ms->SetPreroll(FALSE);
1103 /*Timecode handling*/
1104 lastreftimeRT=reftime1;
1105 lastreftimePTS=packet.pts;
1108 ms->SetSyncPoint(FALSE);
1109 ms->SetTime(NULL,NULL);
1110 ms->SetMediaTime(NULL, NULL);
1111 ms->SetPreroll(FALSE);
1113 // ms->SetSyncPoint(TRUE);
1118 memcpy(ms_buf+ms_pos,buffer+packet.pos_buffer+*samplepos,haveToCopy);
1119 ms->SetActualDataLength(haveToCopy+ms_pos);
1121 *samplepos+=haveToCopy;
1123 return haveToCopy+headerstrip;
1127 *samplepos+=packet.length;
1128 MILLISLEEP(0); //yet not implemented//bad idea
1129 return packet.length;
1133 int VideoWin::getCurrentAudioMediaSample(IMediaSample** ms)
1135 //WaitForSingleObject(filtermutex,INFINITE);
1137 // ReleaseMutex(filtermutex);
1140 if (cur_audio_media_sample) {
1141 *ms=cur_audio_media_sample;//already open
1144 if (!sourcefilter->getCurrentAudioMediaSample(ms)) {
1145 // ReleaseMutex(filtermutex);
1147 if (*ms) (*ms)->SetActualDataLength(0);
1148 cur_audio_media_sample=*ms;
1149 //Don't release the mutex before deliver
1153 int VideoWin::getCurrentVideoMediaSample(IMediaSample** ms)
1155 //WaitForSingleObject(filtermutex,INFINITE);
1157 // ReleaseMutex(filtermutex);
1160 if (cur_video_media_sample) {
1161 *ms=cur_video_media_sample;//already open
1164 if (!sourcefilter->getCurrentVideoMediaSample(ms)) {
1165 // ReleaseMutex(filtermutex);
1167 if (*ms) (*ms)->SetActualDataLength(0);
1169 cur_video_media_sample=*ms;
1170 //Don't release the mutex before deliver
1174 int VideoWin::DeliverAudioMediaSample(){
1175 if (cur_audio_media_sample) {
1176 sourcefilter->DeliverAudioMediaSample(cur_audio_media_sample);
1177 cur_audio_media_sample=NULL;
1179 //ReleaseMutex(filtermutex);
1183 int VideoWin::DeliverVideoMediaSample(){
1184 if (cur_video_media_sample) {
1185 sourcefilter->DeliverVideoMediaSample(cur_video_media_sample);
1186 cur_video_media_sample=NULL;
1188 //ReleaseMutex(filtermutex);
1192 long long VideoWin::SetStartOffset(long long curreftime, bool *rsync)
1196 startoffset=curreftime;//offset is set for audio
1198 offsetvideonotset=false;
1202 if (offsetvideonotset) {
1203 offsetvideonotset=false;
1206 if ( (curreftime-lastrefvideotime)>10000000LL
1207 || (curreftime-lastrefvideotime)<-10000000LL) {//if pts jumps to big resync
1208 startoffset+=curreftime-lastrefvideotime;
1209 lastrefaudiotime+=curreftime-lastrefvideotime;
1211 offsetaudionotset=true;
1218 lastrefvideotime=curreftime;
1224 long long VideoWin::SetStartAudioOffset(long long curreftime, bool *rsync)
1228 startoffset=curreftime;
1230 offsetaudionotset=false;
1232 if (offsetaudionotset) {
1233 offsetaudionotset=false;
1236 if ( (curreftime-lastrefaudiotime)>10000000LL
1237 || (curreftime-lastrefaudiotime)<-10000000LL) {//if pts jumps to big resync
1238 startoffset+=curreftime-lastrefaudiotime;
1239 lastrefvideotime+=curreftime-lastrefaudiotime;
1241 offsetvideonotset=true;
1247 lastrefaudiotime=curreftime;
1251 void VideoWin::ResetTimeOffsets() {
1252 offsetnotset=true; //called from demuxer
1253 offsetvideonotset=true;
1254 offsetaudionotset=true;
1264 void VideoWin::SetAudioVolume(long volume)
1267 if (dsbasicaudio) dsbasicaudio->put_Volume(volume);
1270 void VideoWin::displayIFrame(const UCHAR* buffer, UINT length)
1272 if (!iframemode) EnterIframePlayback();
1274 if (!isdsinited()) return ;
1276 IMediaSample* ms=NULL;
1277 REFERENCE_TIME reftime1=0;
1278 REFERENCE_TIME reftime2=0;
1279 if (!videoon) return;
1281 if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
1287 ms->GetPointer(&ms_buf);
1288 ms_length=ms->GetSize();
1290 /*First Check, if we have an video sample*/
1291 DWORD read_pos = 0, write_pos = 0;
1292 DWORD pattern, packet_length;
1293 DWORD headerstrip=0;
1295 if (length < 4) return ;
1296 //Now we strip the pes header
1297 pattern = (buffer[0] << 16) | (buffer[1] << 8) | (buffer[2]);
1298 while (read_pos + 7 <= length)
1300 pattern = ((pattern << 8) & 0xFFFFFFFF) | buffer[read_pos+3];
1301 if (pattern < 0x000001E0 || pattern > 0x000001EF)
1305 headerstrip=buffer[read_pos+8]+9/*is this right*/;
1306 packet_length = ((buffer[read_pos+4] << 8) | (buffer[read_pos+5])) + 6;
1307 if (read_pos + packet_length > length)
1311 if ((write_pos+packet_length-headerstrip)>ms_length) {
1313 ms->SetSyncPoint(TRUE);
1314 ms->SetDiscontinuity(TRUE);
1316 } else ms->SetSyncPoint(FALSE);
1317 ms->SetTime(NULL,NULL);
1318 ms->SetMediaTime(NULL, NULL);
1319 ms->SetActualDataLength(write_pos);
1320 DeliverVideoMediaSample();
1322 if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
1327 ms_length=ms->GetSize();
1328 ms->GetPointer(&ms_buf);
1330 if (packet_length>headerstrip) {
1331 memcpy(ms_buf+write_pos, buffer+read_pos+headerstrip, packet_length-headerstrip);
1332 write_pos += packet_length-headerstrip;
1334 read_pos += packet_length;
1336 pattern = (buffer[read_pos] << 16) | (buffer[read_pos+1] << 8)
1337 | (buffer[read_pos+2]);
1342 if (first) {ms->SetSyncPoint(TRUE);first=false;}
1343 else ms->SetSyncPoint(FALSE);
1344 ms->SetTime(NULL,NULL);
1345 ms->SetMediaTime(NULL, NULL);
1346 ms->SetActualDataLength(write_pos);
1347 DeliverVideoMediaSample();
1351 // *samplepos+=packet.length;
1352 MILLISLEEP(0); //yet not implemented//bad idea
1357 bool VideoWin::supportsAc3(){
1358 if (sourcefilter != NULL) {
1359 return sourcefilter->supportsAc3();
1365 bool VideoWin::changeAType(int type,IMediaSample* ms){
1366 if (sourcefilter!= NULL) {
1368 return sourcefilter->changeAType(type,ms);
1377 int VideoWin::test()
1382 int VideoWin::test2()