![]() ![]() |
Feb 2 2009, 07:44 PM
Post
#1
|
|
|
Participant Group: New Members Posts: 43 Joined: 2-February 09 Member No.: 11,797 Card: None |
Does anyone have an example of putting a DVB stream through the DirectShow SBE? I've been trying for days to get it to work and all the source filter produces is a black screen.
I'm taking the input from a DVB-S card, through the normal filters to the MPEG demux. I take the video output from the demux, put it through the video analyzer and then onto the sink. I take the audio output from the demux and put it straight to the sink. The source filter connects to ffdshow video and audio decoders before going on to the vide and audio renderers. I have dumped the contents of both graphs and the filters and pins look fine. I've tried connecting all the MPEG demux pins to the sink and that made no difference. The code is in C# using DirectShowLib but a C++ example would be fine. Thanks in advance. |
|
|
|
Feb 2 2009, 08:25 PM
Post
#2
|
|
|
Forum Regular Group: Members Posts: 3,034 Joined: 24-April 04 From: Queensland Member No.: 808 Card: VisionPlus DVB-t |
How are you setting up the SBE?
Are you holding reference on the CreateRecorder's ( IUnknown **pRecordingIUnknown) ? Some code would be good to see where it might be going wrong. |
|
|
|
Feb 3 2009, 06:38 AM
Post
#3
|
|
|
Participant Group: New Members Posts: 43 Joined: 2-February 09 Member No.: 11,797 Card: None |
I don't refer to the CreateRecorder function at all although I have tried that previously.
Here's an edited version of the code (C# I'm afraid). It's spread over a number of methods in the actual class so probably too long to post here. CODE // // Create the SBE sink graph // captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); graph = (IFilterGraph2)new FilterGraph(); captureGraph.SetFiltergraph(graph); mpeg2Demux = (IBaseFilter)new MPEG2Demultiplexer(); hr = graph.AddFilter(this.mpeg2Demux, "MPEG2 Demultiplexer"); DsError.ThrowExceptionForHR(hr); // // Network provider, board filters etc created and added to graph. // // Assuming this is ok as display is ok when rendered directly and // // signal strength is ok when using SBE // videoAnalyzer = (IBaseFilter)new Mpeg2VideoStreamAnalyzer(); hr = graph.AddFilter(videoAnalyzer, "MPEG2 Video Stream Analyzer"); DsError.ThrowExceptionForHR(hr); streamBufferSink = (IBaseFilter)new StreamBufferSink(); hr = graph.AddFilter(streamBufferSink, "Stream Buffer Sink"); DsError.ThrowExceptionForHR(hr); hr = captureGraph.RenderStream(null, MediaType.Audio, mpeg2Demux, null, streamBufferSink); DsError.ThrowExceptionForHR(hr); hr = captureGraph.RenderStream(null, MediaType.Video, mpeg2Demux, null, videoAnalyzer); DsError.ThrowExceptionForHR(hr); hr = captureGraph.RenderStream(null, MediaType.Video, videoAnalyzer, null, streamBufferSink); DsError.ThrowExceptionForHR(hr); // // Create the SBE source graph // graphSource = (IFilterGraph2)new FilterGraph(); streamBufferSource = (IBaseFilter)new StreamBufferSource(); hr = graphSource.AddFilter(streamBufferSource, "Stream Buffer Source"); DsError.ThrowExceptionForHR(hr); hr = ((IStreamBufferSource)streamBufferSource).SetStreamSink((IStreamBufferSink)strea mBufferSink); DsError.ThrowExceptionForHR(hr); mediaSeeking = (IStreamBufferMediaSeeking2)streamBufferSource; // // DirectSound renderer and VMR9 created and configured // // Following code then enumerates source pins and renders them. Any pin that fails to render gets a null renderer. // Debugging log shows video pin connected to VMR9 via ffdshow video decoder and audio pin connected to DirectSound filter via // ffdshow audio decoder. // IEnumPins enumPins = null; IPin[] pin = new IPin[1]; streamBufferSource.EnumPins(out enumPins); while (enumPins.Next(pin.Length, pin, IntPtr.Zero) == 0) { IPin connectedPin = null; hr = pin[0].ConnectedTo(out connectedPin); if (hr != 0) { hr = graphSource.Render(pin[0]); if (hr != 0) { IBaseFilter nullRenderer = getNullRenderer(graphSource, "Null Renderer"); IPin nullPin = null; hr = nullRenderer.FindPin("In", out nullPin); DsError.ThrowExceptionForHR(hr); hr = graphSource.Connect(pin[0], nullPin); DsError.ThrowExceptionForHR(hr); Marshal.ReleaseComObject(pin[0]); } } else Marshal.ReleaseComObject(connectedPin); Marshal.ReleaseComObject(pin[0]); } Marshal.ReleaseComObject(enumPins); In this version I don't do anything with the Sections and Tables pin or TIF pin from the mux but I've tried including those before and it made no difference. (Incidentally the MSDN documentation apparently says these are required but directly rendering works ok even if they are left out). |
|
|
|
Feb 3 2009, 07:42 AM
Post
#4
|
|
|
Forum Regular Group: Members Posts: 3,034 Joined: 24-April 04 From: Queensland Member No.: 808 Card: VisionPlus DVB-t |
QUOTE In this version I don't do anything with the Sections and Tables pin or TIF pin from the mux but I've tried including those before and it made no difference. (Incidentally the MSDN documentation apparently says these are required but directly rendering works ok even if they are left out). No sure what you mean here but the TIF & S&T filters need to be connected to the demux for the BDA model to work.See below some code to setup the sbe, just need to connect the wanted stream A/V pins to the sbe, render the tif & s&t pins submit your tune request and run. m_pRecUnk needs to be held else it wont record anything. CODE //
// Setup and start the Stream Buffer capture // CComPtr <IStreamBufferSink> pISBSi; hr = m_pStreamBufferSink.QueryInterface (&pISBSi); if (FAILED (hr)) { log("Cannot QueryInterface for IStreamBufferSink on Stream Buffer Sink 0x%x\n", hr); return hr; } hr = pISBSi->LockProfile(NULL); if (FAILED (hr)) { log("Cannot LockProfile on Stream Buffer Sink 0x%x\n", hr); return hr; } hr = pISBSi->CreateRecorder(capPath, RECORDING_TYPE_CONTENT, &m_pRecUnk); if (FAILED (hr)) { log("Cannot CreateRecorder on Stream Buffer Sink 0x%x\n", hr); return hr; } CComQIPtr<IStreamBufferRecordControl> pRecControl; REFERENCE_TIME rtStart = 0; hr = m_pRecUnk.QueryInterface (&pRecControl); if (FAILED (hr)) { log("Cannot IQ IStreamBufferRecordControl 0x%x\n", hr); return hr; } log("Enabling Stream Buffer Filter \n"); hr = pRecControl->Start(&rtStart); if (FAILED (hr)) { log("win32-DLL-BDA : Cannot Start Capture on Stream Buffer 0x%x\n", hr); return hr; } |
|
|
|
Feb 3 2009, 09:41 AM
Post
#5
|
|
|
Participant Group: New Members Posts: 43 Joined: 2-February 09 Member No.: 11,797 Card: None |
Do you need the recorder if you use the SBE Source filter linked to the Sink filter using SBE Source SetStreamSink ? I though you only needed the recorder for permanent recordings.
I have DVB-S graph that works fine with or without the TIF and S+T filters. I'm not the only one either - I think it was on the MSDN DirectShow forum that someone was asking if they were needed because they had a graph working without them as well. I'll mimic your example in C# and see if I can get it to work. Incidentally, doesn't the LockProfile call need a file name rather than null? Thanks again for your time. |
|
|
|
Feb 3 2009, 11:13 AM
Post
#6
|
|
|
Forum Regular Group: Members Posts: 3,034 Joined: 24-April 04 From: Queensland Member No.: 808 Card: VisionPlus DVB-t |
QUOTE Do you need the recorder if you use the SBE Source filter linked to the Sink filter using SBE Source SetStreamSink ? No, thought you were trying to record.QUOTE I have DVB-S graph that works fine with or without the TIF and S+T filters. I'm not the only one either - I think it was on the MSDN DirectShow forum that someone was asking if they were needed because they had a graph working without them as well. True, as long as your mapping the demux manually.QUOTE I'll mimic your example in C# and see if I can get it to work. Incidentally, doesn't the LockProfile call need a file name rather than null? From MSDNQUOTE If pszFilename is NULL, the stub file is created in the current directory with a default file name. You may have some permissions issues vista so see here. Also some code from nate's DigitalWatch 7.24 may be of help here. CODE BOOL DVBSourceMSDemuxTimeShift::AddSourceFilters(IGraphBuilder* piGraphBuilder, IMediaControl* piMediaControl)
{ m_piGraphBuilder = piGraphBuilder; m_piMediaControl = piMediaControl; if (m_bInitialised) return FALSE; if (piGraphBuilder == NULL) return FALSE; HRESULT hr; //--- Create Graph --- hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&m_piGraphBuilderSink); if (hr != S_OK) return ErrorMessageBox("Failed Creating Graph Builder for sink graph"); //--- Add To Running Object Table --- (for graphmgr.exe) if (m_pAppData->addToROT != 0) { hr = AddToRot(m_piGraphBuilderSink, &m_rotEntry); if (hr != S_OK) return ErrorMessageBox("Failed adding Source graph to ROT"); } //--- Get InterfacesInFilters --- hr = m_piGraphBuilderSink->QueryInterface(IID_IMediaControl, (void **)&m_piMediaControlSink); if (hr != S_OK) return ErrorMessageBox("Failed to get Media Control interface for sink graph"); //DVB Source hr = AddFilter(m_piGraphBuilderSink, CLSID_DVBSource, m_pfDVBSource, L"DVB Source"); if (hr != S_OK) return FALSE; hr = m_pfDVBSource->QueryInterface(IID_IDVBSource, (void **)&m_piDVBSource); if (hr != S_OK) return ErrorMessageBox("Failed to get DVB Source interface"); hr = m_pfDVBSource->QueryInterface(IID_IDVBCard, (void **)&m_piDVBSourceCard); if (hr != S_OK) return ErrorMessageBox("Failed to get DVB Card interface"); //MPEG-2 Demultiplexer hr = AddFilter(m_piGraphBuilderSink, CLSID_MPEG2Demultiplexer, m_pfMpeg2Demux, L"MPEG-2 Demultiplexer"); if (hr != S_OK) return FALSE; //MPEG-2 Video Stream Analyser hr = AddFilter(m_piGraphBuilderSink, CLSID_Mpeg2VideoStreamAnalyzer, m_pfVideoStreamAnalyzer, L"Video Stream Analyzer"); if (hr != S_OK) return FALSE; //Check that there's a card INT iNumOfCards; m_piDVBSourceCard->get_HWNum(&iNumOfCards); if (iNumOfCards <= 0) return ErrorMessageBox("No cards detected"); if ((m_pAppData->cardNumber <= 0) || (m_pAppData->cardNumber > iNumOfCards)) { char error[256]; sprintf((char*)&error, "Specified card number, %i, is out of range\n%i card(s) found", m_pAppData->cardNumber, iNumOfCards); MessageBox(m_pAppData->hWnd, (char*)&error, "DigitalWatch", MB_OK); return FALSE; } hr = m_piDVBSourceCard->set_CurrentHW(m_pAppData->cardNumber); if (hr != S_OK) return ErrorMessageBox("Error Setting to card"); m_bInitialised = TRUE; return TRUE; } HRESULT DVBSourceMSDemuxTimeShift::Connect() { //Thanks to JoeyBloggs for Timeshifting configuration code HRESULT hr; //Connect DVBSource to MPEG-2 Demultiplexer hr = ConnectPins(m_piGraphBuilderSink, m_pfDVBSource, L"Transponder Stream", m_pfMpeg2Demux, L"MPEG-2 Stream"); if (hr != S_OK) return ErrorMessageBox("Failure: Cannot connect DVB Source to MPEG-2 Demultiplexer"); IMpeg2Demultiplexer* piMpeg2Demux; hr = m_pfMpeg2Demux->QueryInterface(IID_IMpeg2Demultiplexer, (void **)&piMpeg2Demux); if (hr != S_OK) return FALSE; IMPEG2PIDMap *pPidMap = NULL; //------------ Audio ------------- AM_MEDIA_TYPE mtAudio; ZeroMemory(&mtAudio, sizeof(AM_MEDIA_TYPE)); mtAudio.majortype = MEDIATYPE_Audio; if (!m_bAC3) mtAudio.subtype = MEDIASUBTYPE_MPEG1AudioPayload; else mtAudio.subtype = MEDIASUBTYPE_DOLBY_AC3; mtAudio.bFixedSizeSamples = TRUE; mtAudio.bTemporalCompression = 0; mtAudio.lSampleSize = 1; mtAudio.formattype = FORMAT_WaveFormatEx; mtAudio.pUnk = NULL; mtAudio.cbFormat = sizeof g_MPEG1AudioFormat; mtAudio.pbFormat = g_MPEG1AudioFormat; IPin *pPinAudio; if (!m_bAC3) hr = piMpeg2Demux->CreateOutputPin(&mtAudio, L"Audio", &pPinAudio); else hr = piMpeg2Demux->CreateOutputPin(&mtAudio, L"AC3", &pPinAudio); if (hr != S_OK) return FALSE; // Map the PID. hr = pPinAudio->QueryInterface(IID_IMPEG2PIDMap, (void**)&pPidMap); if (SUCCEEDED(hr)) { ULONG Pid[] = { m_lAPid }; // Map any desired PIDs. ULONG cPid = 1; hr = pPidMap->MapPID(cPid, Pid, MEDIA_ELEMENTARY_STREAM); pPidMap->Release(); } pPinAudio->Release(); //---------- Video ------------ AM_MEDIA_TYPE mtVideo; ZeroMemory(&mtVideo, sizeof(AM_MEDIA_TYPE)); mtVideo.majortype = KSDATAFORMAT_TYPE_VIDEO; mtVideo.subtype = MEDIASUBTYPE_MPEG2_VIDEO; mtVideo.bFixedSizeSamples = TRUE; mtVideo.bTemporalCompression = 0; mtVideo.lSampleSize = 1; mtVideo.formattype = FORMAT_MPEG2Video; mtVideo.pUnk = NULL; mtVideo.cbFormat = sizeof(g_Mpeg2ProgramVideo); mtVideo.pbFormat = g_Mpeg2ProgramVideo; IPin *pPinVideo; hr = piMpeg2Demux->CreateOutputPin(&mtVideo, L"Video", &pPinVideo); if (hr != S_OK) return FALSE; // Map the PID. hr = pPinVideo->QueryInterface(IID_IMPEG2PIDMap, (void**)&pPidMap); if (SUCCEEDED(hr)) { ULONG Pid[] = { m_lVPid }; // Map any desired PIDs. ULONG cPid = 1; hr = pPidMap->MapPID(cPid, Pid, MEDIA_ELEMENTARY_STREAM); pPidMap->Release(); } pPinVideo->Release(); // Create a new registry key to hold our settings. HKEY hkey = 0; long lRes = RegCreateKey(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\DigitalWatch\\StreamBufferConfig"), &hkey); hr = ::CoCreateInstance(CLSID_StreamBufferConfig, NULL, CLSCTX_INPROC_SERVER, IID_IStreamBufferConfigure, reinterpret_cast<void**>(&m_piStreamBufferConfigure) ); if (SUCCEEDED(hr)) { IStreamBufferInitialize* piStreamBufferConfigInitialize = NULL; hr = m_piStreamBufferConfigure->QueryInterface(IID_IStreamBufferInitialize, reinterpret_cast<void**>(&piStreamBufferConfigInitialize) ); if (SUCCEEDED(hr)) { hr = piStreamBufferConfigInitialize->SetHKEY(hkey); if (FAILED(hr)) { ErrorMessageBox("Failure: Could not set HKEY on stream buffer config initialize interface"); } hr = piStreamBufferConfigInitialize->Release(); hr = m_piStreamBufferConfigure->SetBackingFileDuration(10 * 60); // ie 600 seconds or 10 minutes hr = m_piStreamBufferConfigure->SetBackingFileCount (int(m_pAppData->timeshiftBufferMinutes/10), int(m_pAppData->timeshiftBufferMinutes/10)+2 ); wchar_t folder[512]; mbstowcs((wchar_t*)&folder, (char*)&m_pAppData->timeshiftFolder, 512); hr = m_piStreamBufferConfigure->SetDirectory( (wchar_t*)&folder ); } else { ErrorMessageBox("Failure: Could not obtain stream buffer config initialize interface"); } } else { ErrorMessageBox("Failure: Could not create stream buffer configure"); } //Stream Buffer Sink hr = AddFilter(m_piGraphBuilderSink, CLSID_StreamBufferSink, m_pfSink, L"Stream Buffer Sink"); if (hr != S_OK) return FALSE; IStreamBufferInitialize* piStreamBufferSinkInitialize = NULL; hr = m_pfSink->QueryInterface(IID_IStreamBufferInitialize, reinterpret_cast<void**>(&piStreamBufferSinkInitialize) ); if (SUCCEEDED(hr)) { hr = piStreamBufferSinkInitialize->SetHKEY(hkey); if (FAILED(hr)) { ErrorMessageBox("Failure: Could not set HKEY on stream buffer sink initialize interface"); } hr = piStreamBufferSinkInitialize->Release(); } else { ErrorMessageBox("Failure: Could not obtain stream buffer sink initialize interface"); } hr = m_pfSink->QueryInterface(IID_IStreamBufferSink, (void **)&m_piSink); if (hr != S_OK) return ErrorMessageBox("Failure: Could not get source buffer interface"); //Connect MPEG-2 Demultiplexer to Video Stream Analyzer hr = ConnectPins(m_piGraphBuilderSink, m_pfMpeg2Demux, L"Video", m_pfVideoStreamAnalyzer, L"in"); if (hr != S_OK) return ErrorMessageBox("Failure: Cannot connect MPEG-2 Demultiplexer to Video Stream Analyzer"); //Connect Video Stream Analyzer to Stream Buffer Sink hr = ConnectPins(m_piGraphBuilderSink, m_pfVideoStreamAnalyzer, L"out", m_pfSink, L"DVR In - 1"); if (hr != S_OK) return ErrorMessageBox("Failure: Cannot connect Video Stream Analyzer to Stream Buffer Sink"); //Connect MPEG-2 Demultiplexer Audio to Stream Buffer Sink if (!m_bAC3) hr = ConnectPins(m_piGraphBuilderSink, m_pfMpeg2Demux, L"Audio", m_pfSink, L"DVR In - 2"); else hr = ConnectPins(m_piGraphBuilderSink, m_pfMpeg2Demux, L"AC3", m_pfSink, L"DVR In - 2"); if (hr != S_OK) return ErrorMessageBox("Failure: Cannot connect MPEG-2 Demultiplexer to Stream Buffer Sink"); //hr = m_piSink->LockProfile(L"D:\\timeshift.tmp"); if (strcmp(m_pAppData->timeshiftFolder, "") == 0) { hr = m_piSink->LockProfile(NULL); if (hr != S_OK) return ErrorMessageBox("Failure: Cannot lock profile"); } else { char lockingFile[512]; sprintf((char*)&lockingFile, "%s\\timeshift.mpg", m_pAppData->timeshiftFolder); wchar_t wlockingFile[512]; mbstowcs((wchar_t*)&wlockingFile, lockingFile, 512); hr = m_piSink->LockProfile(wlockingFile); if (hr != S_OK) return ErrorMessageBox("Failure: Cannot lock profile"); } hr = m_piMediaControlSink->Run(); if ((hr != S_OK) && (hr != S_FALSE)) return ErrorMessageBox("Error running sink graph"); //Stream Buffer Source hr = AddFilter(m_piGraphBuilder, CLSID_StreamBufferSource, m_pfSource, L"Stream Buffer Source"); if (hr != S_OK) return FALSE; IStreamBufferInitialize* piStreamBufferSourceInitialize = NULL; hr = m_pfSource->QueryInterface(IID_IStreamBufferInitialize, reinterpret_cast<void**>(&piStreamBufferSourceInitialize) ); if (SUCCEEDED(hr)) { hr = piStreamBufferSourceInitialize->SetHKEY(hkey); if (FAILED(hr)) { ErrorMessageBox("Failure: Could not set HKEY on stream buffer source initialize interface"); } hr = piStreamBufferSourceInitialize->Release(); } else { ErrorMessageBox("Failure: Could not obtain stream buffer source initialize interface"); } hr = m_pfSource->QueryInterface(IID_IStreamBufferSource, (void **)&m_piSource); if (hr != S_OK) return ErrorMessageBox("Failure: Could not get source buffer interface"); m_piSource->SetStreamSink(m_piSink); return TRUE; } |
|
|
|
Feb 3 2009, 04:39 PM
Post
#7
|
|
|
Participant Group: New Members Posts: 43 Joined: 2-February 09 Member No.: 11,797 Card: None |
Thanks a bunch Bear (and to Nate). The code from DigitalWatch showed me what was wrong.
You need to call Run() on the sink graph media control after the sink is locked. With that added everything worked. On the other topics - I don't do any mapping of the demux and it still works without the TIF and S+T in the graph. I'll look in to this a bit more. I read the MSDN comment on LockProfile and null just after I sent the last reply - mouse used before brain problem again. Thanks again for your help. Steve |
|
|
|
May 3 2010, 01:11 PM
Post
#8
|
|
|
Participant Group: New Members Posts: 20 Joined: 31-December 09 Member No.: 12,983 Card: DNTV TinyTwin USB |
Hi NZ Steve and bear,
I'm mucking around with Istreambuffersource.setstreamsink ( via directshowlib ) i am getting a HR of 0x80004002 ("no such interface supported") when i use SetStreamSink on the IStreamBufferSource interface. here is the code hr = (sbeSource as DirectShowLib.SBE.IStreamBufferSource).SetStreamSink(sbeSink as DirectShowLib.SBE.IStreamBufferSink); If i use IFileSourceFilter.Load on the streambuffersource, it works, so im pretty sure my graphs are correct. Does this mean that directshowlib doesnt have setstreamsink? Any pointers on how to fix this would be much appreciated also, my graphs are in the same process Cheers Anton -------------------- |
|
|
|
May 3 2010, 05:40 PM
Post
#9
|
|
|
Forum Regular Group: Members Posts: 3,034 Joined: 24-April 04 From: Queensland Member No.: 808 Card: VisionPlus DVB-t |
Hi, It's a bit hard without the rest of the code but have you locked the profile on the sink?
look at IStreamBufferSink::LockProfile Method. |
|
|
|
May 3 2010, 07:24 PM
Post
#10
|
|
|
Participant Group: New Members Posts: 20 Joined: 31-December 09 Member No.: 12,983 Card: DNTV TinyTwin USB |
thanks for the reply Bear,
i think i found where the problem is, but no solution yet. i am coding under this library called WPFMediakit. When i tried it without wpfmediakit, it worked straight off. I now need to find what is causing it under wpfmediakit. cheers Anton -------------------- |
|
|
|
Jan 10 2012, 06:38 PM
Post
#11
|
|
|
Be nice to me, I am new. Group: New Members Posts: 3 Joined: 27-December 11 Member No.: 14,756 Card: Twinhan DVB-S USB BOX |
TRY MY SOFTWARE C#
http://www.bilisimbiliyor.com/projects/Tur...Capture_DVB.rar |
|
|
|
![]() ![]() |
|
Lo-Fi Version | Time is now: 26th May 2013 - 12:23 AM |