From 8fc21850144689f3c85458c8e63b346a81263a9e Mon Sep 17 00:00:00 2001 From: Chris Tallon Date: Sun, 24 Sep 2006 15:19:21 +0000 Subject: [PATCH] Win code for ffwd/fbwd --- audiowin.cc | 10 ++- dssourcepin.cc | 228 +++++++++++++++++++++++++------------------------ readme.win | 1 + videowin.cc | 193 ++++++++++++++++++++++++++++++++++++++++- videowin.h | 5 ++ vompwin.rc | 4 +- 6 files changed, 323 insertions(+), 118 deletions(-) diff --git a/audiowin.cc b/audiowin.cc index 3ab1b78..3e04813 100644 --- a/audiowin.cc +++ b/audiowin.cc @@ -113,7 +113,8 @@ int AudioWin::unPause() int AudioWin::reset() { - if (!initted) return 0; + + if (!initted){return 0;} return ((VideoWin*)Video::getInstance())->dsreset(); } @@ -164,8 +165,14 @@ UINT AudioWin::DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer, UINT *samplepos) { + /*First Check, if we have an audio sample*/ VideoWin *vw=(VideoWin*)Video::getInstance(); + if (vw->InIframemode()) { + samplepos=0; + MILLISLEEP(10); + return 0; //Not in iframe mode! + } IMediaSample* ms=NULL; REFERENCE_TIME reftime1=0; REFERENCE_TIME reftime2=0; @@ -197,6 +204,7 @@ UINT AudioWin::DeliverMediaPacket(MediaPacket packet, } else { if (!firstsynched) {// *samplepos=packet.length;//if we have not processed at least one + return packet.length;//synched packet ignore it! } } diff --git a/dssourcepin.cc b/dssourcepin.cc index 0ce629a..fab2c86 100644 --- a/dssourcepin.cc +++ b/dssourcepin.cc @@ -37,116 +37,118 @@ DsSourcePin::~DsSourcePin() } -HRESULT DsSourcePin::GetMediaType(int iPosition, CMediaType *pmt) -{ - HRESULT hr; - ASSERT(pmt); - pmt->InitMediaType(); - if (isaudiopin){ - if (iPosition==0) { - pmt->SetType(&MEDIATYPE_Audio); - MPEG1WAVEFORMAT wfe; - ZeroMemory(&wfe,sizeof(wfe)); - wfe.wfx.cbSize=22; - wfe.wfx.nSamplesPerSec=48000; - wfe.wfx.nChannels=2; - wfe.wfx.nAvgBytesPerSec=32000; - wfe.wfx.nBlockAlign=768; - wfe.wfx.wFormatTag=WAVE_FORMAT_MPEG; - wfe.fwHeadLayer=2; - wfe.dwHeadBitrate=256000; - wfe.fwHeadMode=ACM_MPEG_STEREO; - wfe.fwHeadModeExt=1; - wfe.wHeadEmphasis=1; - wfe.fwHeadFlags=ACM_MPEG_ID_MPEG1 |ACM_MPEG_ORIGINALHOME | ACM_MPEG_PROTECTIONBIT; - pmt->SetSubtype(&MEDIASUBTYPE_MPEG2_AUDIO); - pmt->SetFormatType(&FORMAT_WaveFormatEx); - pmt->SetFormat((BYTE*)&wfe,sizeof(wfe)); - pmt->SetSampleSize(0); - hr=S_OK; - - - } else { - hr=VFW_S_NO_MORE_ITEMS ; - } - } else { - if (iPosition == 0) { - pmt->SetType(&MEDIATYPE_Video); - hr=S_OK; - pmt->SetSubtype(&MEDIASUBTYPE_MPEG2_VIDEO); - pmt->SetFormatType(&FORMAT_MPEG2Video); - - MPEG2VIDEOINFO hdr; - ZeroMemory(&hdr,sizeof(hdr)); - hdr.dwProfile=AM_MPEG2Profile_Main; - hdr.dwLevel=AM_MPEG2Level_Main; - hdr.hdr.bmiHeader.biSize = sizeof(hdr.hdr.bmiHeader); - hdr.hdr.bmiHeader.biWidth = 720; - hdr.hdr.bmiHeader.biHeight = 568; - pmt->SetFormat((BYTE*)&hdr,sizeof(hdr)); - } else { - hr=VFW_S_NO_MORE_ITEMS; - } - } - return hr ; -} - -// No description -HRESULT DsSourcePin::CheckMediaType(const CMediaType *pmt) -{ - HRESULT res; - ASSERT (pmt); - if (isaudiopin) { - bool subtype=false; -#if 0 /* For future demands ac3 */ - subtype=pmt->subtype==(MEDIASUBTYPE_DOLBY_AC3); -#endif - subtype=(pmt->subtype==(MEDIASUBTYPE_MPEG2_AUDIO)); - if (pmt->majortype==MEDIATYPE_Audio && subtype) { - res = S_OK ; - } else { - res = S_FALSE ; - } - } else { - if (pmt->majortype==MEDIATYPE_Video && - pmt-> subtype==MEDIASUBTYPE_MPEG2_VIDEO) { - res = S_OK ; - } else { - res = S_FALSE ; - } - } - return res; -} - -HRESULT DsSourcePin::DecideBufferSize(IMemAllocator *pa,ALLOCATOR_PROPERTIES *all_pp){ - HRESULT hr; - CAutoLock al(m_pFilter->GetLock()); - CheckPointer(pa, E_POINTER); - CheckPointer(all_pp, E_POINTER); - if (isaudiopin) { - if (all_pp->cBuffers*all_pp->cbBuffer < 300*64*1024) - { - all_pp->cBuffers = 300; - all_pp->cbBuffer = 64*1024; - } - } else { - if (all_pp->cBuffers*all_pp->cbBuffer < 300*64*1024) - { - all_pp->cBuffers = 300; - all_pp->cbBuffer = 64*1024; - } - } - - ALLOCATOR_PROPERTIES all_pp_cur; - hr =pa->SetProperties(all_pp,&all_pp_cur); - if (FAILED(hr)) - { - return hr; - } - if (all_pp_cur.cbBuffer*all_pp_cur.cBuffers < all_pp->cBuffers*all_pp->cbBuffer) - { - return E_FAIL; - } - - return S_OK; -} +HRESULT DsSourcePin::GetMediaType(int iPosition, CMediaType *pmt) +{ + HRESULT hr; + ASSERT(pmt); + pmt->InitMediaType(); + if (isaudiopin){ + if (iPosition==0) { + pmt->SetType(&MEDIATYPE_Audio); + MPEG1WAVEFORMAT wfe; + ZeroMemory(&wfe,sizeof(wfe)); + wfe.wfx.cbSize=22; + wfe.wfx.nSamplesPerSec=48000; + wfe.wfx.nChannels=2; + wfe.wfx.nAvgBytesPerSec=32000; + wfe.wfx.nBlockAlign=768; + wfe.wfx.wFormatTag=WAVE_FORMAT_MPEG; + wfe.fwHeadLayer=2; + wfe.dwHeadBitrate=256000; + wfe.fwHeadMode=ACM_MPEG_STEREO; + wfe.fwHeadModeExt=1; + wfe.wHeadEmphasis=1; + wfe.fwHeadFlags=ACM_MPEG_ID_MPEG1 |ACM_MPEG_ORIGINALHOME | ACM_MPEG_PROTECTIONBIT; + pmt->SetSubtype(&MEDIASUBTYPE_MPEG2_AUDIO); + pmt->SetFormatType(&FORMAT_WaveFormatEx); + pmt->SetFormat((BYTE*)&wfe,sizeof(wfe)); + pmt->SetSampleSize(0); + hr=S_OK; + + + } else { + hr=VFW_S_NO_MORE_ITEMS ; + } + } else { + if (iPosition == 0) { + pmt->SetType(&MEDIATYPE_Video); + hr=S_OK; + pmt->SetSubtype(&MEDIASUBTYPE_MPEG2_VIDEO); + pmt->SetFormatType(&FORMAT_MPEG2Video); + + MPEG2VIDEOINFO hdr; + ZeroMemory(&hdr,sizeof(hdr)); + hdr.dwProfile=AM_MPEG2Profile_Main; + hdr.dwLevel=AM_MPEG2Level_Main; + hdr.hdr.bmiHeader.biSize = sizeof(hdr.hdr.bmiHeader); + hdr.hdr.bmiHeader.biWidth = 720; + hdr.hdr.bmiHeader.biHeight = 568; + pmt->SetFormat((BYTE*)&hdr,sizeof(hdr)); + } else { + hr=VFW_S_NO_MORE_ITEMS; + } + } + return hr ; +} + +// No description +HRESULT DsSourcePin::CheckMediaType(const CMediaType *pmt) +{ + HRESULT res; + ASSERT (pmt); + if (isaudiopin) { + bool subtype=false; +#if 0 /* For future demands ac3 */ + subtype=pmt->subtype==(MEDIASUBTYPE_DOLBY_AC3); +#endif + subtype=(pmt->subtype==(MEDIASUBTYPE_MPEG2_AUDIO)); + if (pmt->majortype==MEDIATYPE_Audio && subtype) { + res = S_OK ; + } else { + res = S_FALSE ; + } + } else { + if (pmt->majortype==MEDIATYPE_Video && + pmt-> subtype==MEDIASUBTYPE_MPEG2_VIDEO) { + res = S_OK ; + } else { + res = S_FALSE ; + } + } + return res; +} + +HRESULT DsSourcePin::DecideBufferSize(IMemAllocator *pa,ALLOCATOR_PROPERTIES *all_pp){ + HRESULT hr; + CAutoLock al(m_pFilter->GetLock()); + CheckPointer(pa, E_POINTER); + CheckPointer(all_pp, E_POINTER); + if (isaudiopin) { + if (all_pp->cBuffers*all_pp->cbBuffer < 300*64*1024) + { + //all_pp->cBuffers = 300;//old + all_pp->cBuffers = 10; + all_pp->cbBuffer = 64*1024; + } + } else { + if (all_pp->cBuffers*all_pp->cbBuffer < 300*64*1024) + { + //all_pp->cBuffers = 300;//old + all_pp->cBuffers = 30; + all_pp->cbBuffer = 64*1024; + } + } + + ALLOCATOR_PROPERTIES all_pp_cur; + hr =pa->SetProperties(all_pp,&all_pp_cur); + if (FAILED(hr)) + { + return hr; + } + if (all_pp_cur.cbBuffer*all_pp_cur.cBuffers < all_pp->cBuffers*all_pp->cbBuffer) + { + return E_FAIL; + } + + return S_OK; +} diff --git a/readme.win b/readme.win index d487b4c..2ac59dd 100644 --- a/readme.win +++ b/readme.win @@ -103,3 +103,4 @@ Firewall If vomp for Windows stops at "Locating server" or "Connecting to VDR", please configure your firewall so that vomp for windows can communicate with the vompserver on port 3024 (UDP and TCP). + diff --git a/videowin.cc b/videowin.cc index b2cd880..e8b014a 100644 --- a/videowin.cc +++ b/videowin.cc @@ -58,6 +58,7 @@ VideoWin::VideoWin() pseudotvsize=0; videoposx=0; videoposy=0; + iframemode=false;//We are not in Iframe mode at begining @@ -207,6 +208,7 @@ int VideoWin::dsplay() { if (!initted) return 0; CleanupDS(); + //Build filter graph HRESULT hres; @@ -308,10 +310,109 @@ int VideoWin::dsplay() dsgraphbuilder->QueryInterface(IID_IBasicAudio,(void **) &dsbasicaudio); dsmediacontrol->Run(); + iframemode=false;//exit iframe mode ReleaseMutex(filtermutex); return 1; } +int VideoWin::EnterIframePlayback() +{ + if (!initted) return 0; + CleanupDS(); + iframemode=true;//enter iframe mode + //Build filter graph + HRESULT hres; + if (hres=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER, + IID_IGraphBuilder,(void**)&dsgraphbuilder)!=S_OK) { + return 0; + } +#ifdef DS_DEBUG + AddToRot(dsgraphbuilder,&graphidentifier); +#endif + //So this is the real code, this prevents the feeder from calling noexisting objects! + WaitForSingleObject(filtermutex,INFINITE); + //firstsynched=false; + sourcefilter=new DsSourceFilter(); //Creating our Source filter for pushing Data + // to DirectShow + if (hres=dsgraphbuilder->AddFilter(sourcefilter,L"Vomp Win Source Filter")!=S_OK) { + Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Vomp Source Filter!"); + CleanupDS(); + ReleaseMutex(filtermutex); + return 0; + } +#ifdef DO_VIDEO + if (videoon) { + //We alloc the vmr9 as next step + if (hres=CoCreateInstance(CLSID_VideoMixingRenderer9,0, + CLSCTX_INPROC_SERVER,IID_IBaseFilter,(void**) &dsvmrrenderer)!=S_OK) { + Log::getInstance()->log("VideoWin", Log::WARN ,"Failed creating VMR9 renderer!"); + CleanupDS(); + ReleaseMutex(filtermutex); + return 0; + } + /*VMR 9 stuff**/ + if (hres=dsgraphbuilder->AddFilter(dsvmrrenderer,L"VMR9")!=S_OK) { + CleanupDS(); + Log::getInstance()->log("VideoWin", Log::WARN ,"Failed adding VMR9 renderer!"); + ReleaseMutex(filtermutex); + return 0; + } + IVMRFilterConfig9* vmrfilconfig; + if (dsvmrrenderer->QueryInterface(IID_IVMRFilterConfig9,(void**)&vmrfilconfig)!=S_OK) { + CleanupDS(); + Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Filterconfig interface!"); + ReleaseMutex(filtermutex); + return 0; + } + vmrfilconfig->SetRenderingMode(VMR9Mode_Renderless); + vmrfilconfig->Release(); + + if (dsvmrrenderer->QueryInterface(IID_IVMRSurfaceAllocatorNotify9,(void**)& dsvmrsurfnotify)!=S_OK) { + CleanupDS(); + Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Surface Allocator interface!"); + ReleaseMutex(filtermutex); + return 0; + } + allocatorvmr=new DsAllocator(); + dsvmrsurfnotify->AdviseSurfaceAllocator(NULL,allocatorvmr); + allocatorvmr->AdviseNotify(dsvmrsurfnotify); + + /*VMR 9 stuff end */ + IFilterGraph2*fg2=NULL; + if (dsgraphbuilder->QueryInterface(IID_IFilterGraph2,(void**)&fg2)!=S_OK) { + Log::getInstance()->log("VideoWin", Log::WARN , "Failed querying for FilterGraph2 Interface!"); + CleanupDS(); + ReleaseMutex(filtermutex); + return 0; + } + if (hres=fg2->RenderEx(sourcefilter->GetPin(1)/*video*/, + AM_RENDEREX_RENDERTOEXISTINGRENDERERS,NULL)!=S_OK) { + Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering Video!"); + fg2->Release(); + CleanupDS(); + ReleaseMutex(filtermutex); + return 0; + } + fg2->Release(); + } +#endif +/* if (hres=CoCreateInstance(CLSID_SystemClock,NULL,CLSCTX_INPROC_SERVER, + IID_IReferenceClock,(void**)&dsrefclock)!=S_OK) { + return 0; + }*/ + + dsgraphbuilder->QueryInterface(IID_IMediaFilter,(void **) &dsmediafilter); + dsmediafilter->SetSyncSource(/*dsrefclock*/NULL); //Run as fast as you can! + + dsgraphbuilder->QueryInterface(IID_IMediaControl,(void **) &dsmediacontrol); + dsgraphbuilder->QueryInterface(IID_IBasicAudio,(void **) &dsbasicaudio); + + dsmediacontrol->Run(); + ReleaseMutex(filtermutex); + return 1; + +} + int VideoWin::dsstop() { if (!initted) return 0; @@ -343,6 +444,7 @@ int VideoWin::dsreset() if (!initted) return 0; videoposx=0; videoposy=0; + iframemode=false;//exit iframe mode CleanupDS(); return 1; @@ -405,7 +507,7 @@ ULLONG VideoWin::getCurrentTimestamp() { REFERENCE_TIME startoffset; REFERENCE_TIME ncr_time; - + if (iframemode) return 0; //Not in iframe mode! if (!dsrefclock || !sourcefilter) return 0; FILTER_STATE state; sourcefilter->GetState(10,&state); @@ -516,7 +618,11 @@ UINT VideoWin::DeliverMediaPacket(MediaPacket packet, /*First Check, if we have an audio sample*/ #ifdef DO_VIDEO /*First Check, if we have an audio sample*/ - + if (iframemode) { + samplepos=0; + MILLISLEEP(10); + return 0; //Not in iframe mode! + } IMediaSample* ms=NULL; REFERENCE_TIME reftime1=0; REFERENCE_TIME reftime2=0; @@ -756,6 +862,89 @@ void VideoWin::SetAudioVolume(long volume) if (dsbasicaudio) dsbasicaudio->put_Volume(volume); } +void VideoWin::displayIFrame(const UCHAR* buffer, UINT length) +{ + if (!iframemode) EnterIframePlayback(); + + +#ifdef DO_VIDEO + IMediaSample* ms=NULL; + REFERENCE_TIME reftime1=0; + REFERENCE_TIME reftime2=0; + if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample + MILLISLEEP(10); + return ; + } + BYTE *ms_buf; + DWORD ms_length; + ms->GetPointer(&ms_buf); + ms_length=ms->GetSize(); + + /*First Check, if we have an video sample*/ + DWORD read_pos = 0, write_pos = 0; + DWORD pattern, packet_length; + DWORD headerstrip=0; + bool first=true; + if (length < 4) return ; + //Now we strip the pes header + pattern = (buffer[0] << 16) | (buffer[1] << 8) | (buffer[2]); + while (read_pos + 7 <= length) + { + pattern = ((pattern << 8) & 0xFFFFFFFF) | buffer[read_pos+3]; + if (pattern < 0x000001E0 || pattern > 0x000001EF) + read_pos++; + else + { + headerstrip=buffer[read_pos+8]+9/*is this right*/; + packet_length = ((buffer[read_pos+4] << 8) | (buffer[read_pos+5])) + 6; + if (read_pos + packet_length > length) + read_pos = length; + else + { + if ((write_pos+packet_length-headerstrip)>ms_length) { + if (first) {ms->SetSyncPoint(TRUE);first=false;} + else ms->SetSyncPoint(FALSE); + ms->SetTime(NULL,NULL); + ms->SetMediaTime(NULL, NULL); + ms->SetActualDataLength(write_pos); + DeliverVideoMediaSample(); + + if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample + MILLISLEEP(10); + return ; + } + write_pos=0; + ms_length=ms->GetSize(); + ms->GetPointer(&ms_buf); + } + if (packet_length-headerstrip>0) { + memcpy(ms_buf+write_pos, buffer+read_pos+headerstrip, packet_length-headerstrip); + write_pos += packet_length-headerstrip; + } + read_pos += packet_length; + + pattern = (buffer[read_pos] << 16) | (buffer[read_pos+1] << 8) + | (buffer[read_pos+2]); + } + } + } + + if (first) {ms->SetSyncPoint(TRUE);first=false;} + else ms->SetSyncPoint(FALSE); + ms->SetTime(NULL,NULL); + ms->SetMediaTime(NULL, NULL); + ms->SetActualDataLength(write_pos); + DeliverVideoMediaSample(); + +#else + + *samplepos+=packet.length; + MILLISLEEP(0); //yet not implemented//bad idea + return packet.length; +#endif +} + + #ifdef DEV int VideoWin::test() { diff --git a/videowin.h b/videowin.h index 23da5fe..e4e8603 100644 --- a/videowin.h +++ b/videowin.h @@ -59,6 +59,7 @@ class VideoWin : public Video int sync(); int play(); int dsplay(); + bool InIframemode() {return iframemode;}; int stop(); int dsstop(); int pause(); @@ -100,6 +101,8 @@ class VideoWin : public Video void turnVideoOn(){videoon=true;}; void turnVideoOff(){videoon=false;}; + + virtual void displayIFrame(const UCHAR* buffer, UINT length); unsigned int getPosx() {return videoposx;}; unsigned int getPosy() {return videoposy;}; @@ -110,6 +113,7 @@ class VideoWin : public Video int test2(); #endif private: + int EnterIframePlayback(); IMediaControl* dsmediacontrol; IGraphBuilder* dsgraphbuilder; @@ -136,6 +140,7 @@ private: bool firstsynched; bool audioon; bool videoon; + bool iframemode; UCHAR pseudotvsize; REFERENCE_TIME lastreftimeRT; ULLONG lastreftimePTS; diff --git a/vompwin.rc b/vompwin.rc index 29410ad..b4620a3 100644 --- a/vompwin.rc +++ b/vompwin.rc @@ -24,8 +24,8 @@ BEGIN VK_OEM_PLUS, APPCOMMAND_MEDIA_CHANNEL_UP, VIRTKEY, CONTROL, NOINVERT VK_OEM_PLUS, APPCOMMAND_MEDIA_CHANNEL_UP, VIRTKEY, NOINVERT VK_PRIOR, APPCOMMAND_MEDIA_CHANNEL_UP, VIRTKEY, NOINVERT - "F", APPCOMMAND_MEDIA_FAST_FORWARD, VIRTKEY, SHIFT, CONTROL, - NOINVERT + "F", APPCOMMAND_MEDIA_FAST_FORWARD, VIRTKEY, SHIFT, CONTROL, NOINVERT + "B", APPCOMMAND_MEDIA_REWIND, VIRTKEY, SHIFT, CONTROL, NOINVERT VK_F8, APPCOMMAND_VOLUME_MUTE, VIRTKEY, NOINVERT "P", APPCOMMAND_MEDIA_PAUSE, VIRTKEY, CONTROL, NOINVERT "P", APPCOMMAND_MEDIA_PLAY, VIRTKEY, SHIFT, CONTROL, -- 2.39.2