Help - Search - Members - Calendar
Full Version: BDA Tuner Device Frequency Locked Detection
DVB Owners Discussion Forum - dvbowners.com > Technical & Development Forums > BDA Driver Development
null_pointer
Does anyone know hoe to detect if a BDA Tuner device is locked on to a frequency or not?

From the SDK docs it looks like you should be able to query for the IBDA_SignalStatistics Interface on the tuner device and then call get_SignalLocked function to see if the signal is locked or not. The problem is that I can not query for the interface as I always get "Not Found".

Does anyone know how to query for this interface successfully?
bionicdonkey
I don't know if this will help, but i am/was having problems with the tune request not using the default locator, so i couldn't get the correct channel. i think this is why the channel changing doesn't work in the BDASample.
null_pointer
It works perfectly for me, there are people that are having problems and I think it is because the tuner device is not locking onto the frequency correctly when a tune request is submitted.

I just want to be able to query the Tuner device and then if the frequency is not locked submit the tune request again etc.
bionicdonkey
I got to work now aswell, my dx install was buggered. as for the signal locked, the only ways would be using IBDA_SignalStatistics. Is the interface on the Tuner Device? The only other things that i've come accross that may help is ITuner::Validate & IDVBTLocator::get_OtherFrequencyInUse
null_pointer
ITuner::Validate
This will only tell you if you are submiting the correct sort of Tune Request to the Network Provider, ie. you are submitting a IDVBTuneRequest to a DVB Network Provider etc.

IDVBTLocator::get_OtherFrequencyInUse
From the SDK docs "The get_OtherFrequencyInUse method indicates whether the frequency is being used by another DVB-T broadcaster" I am not sure how this would help.
bionicdonkey
I was only guessing.
this is what i wrote for digitalwatch , not sure if it works, cause i can't get the anything out of the function, even if i manully put in values.
CODE
void BDAInput::GetQuality(BOOL &Lock, int &Strength, int &Quality) {



    HRESULT hr;



   CComPtr <ICaptureGraphBuilder2> piCaptureGraphBuilder;  

    CComPtr <IBaseFilter> pBaseFilter;

   CComPtr <IBDA_SignalStatistics> piSignalStats;



    hr = piCaptureGraphBuilder->FindInterface(NULL, NULL, pBaseFilter, IID_IBDA_SignalStatistics, reinterpret_cast<void **>(&piSignalStats));



    switch (hr) {

 case S_OK:

     piSignalStats->get_SignalQuality(reinterpret_cast<LONG *>(Quality));

     piSignalStats->get_SignalStrength(reinterpret_cast<LONG *>(Strength));

     piSignalStats->get_SignalLocked(reinterpret_cast<BOOLEAN *>(Lock));

     break;

 case E_FAIL:

     ErrorMessageBox("Failed to find IBDA_SignalStatistics Interface");

     break;

 case E_NOINTERFACE:

     ErrorMessageBox("No such interface supported");

     break;

 case E_POINTER:

     ErrorMessageBox("NULL pointer argument");

     break;

    }

}
Spectrum
Are you saying get_SignalLocked() is not working???

Spectrum
null_pointer
@Spectrum,
I can not query for the IID_IBDA_SignalStatistics interface on the Tuner filter, I just get "Interface not found".

@bionicdonkey,
So when you call your code do you get
case E_NOINTERFACE:
That is what I get when I try to query for the IID_IBDA_SignalStatistics interface.
bionicdonkey
i get nothing whatsoever, digitalwatch just says 0. i'll try calling it from somewhere else
null_pointer
When you query for the interface do you get a pointer to it or do you get an error HRESULT of E_NOINTERFACE?
nate
QUOTE
this is what i wrote for digitalwatch , not sure if it works, cause i can't get the anything out of the function, even if i manully put in values.
This might be an obvious question, but have you uncommented the line in StateInformation.cpp that calls that method?

m_pFilterGraph->GetDVBInput()->GetQuality(signalLock, signalStrength, signalQuality);
bionicdonkey
i just picked up on that
JoeyBloggs
I;ve never managed to get it to work either. Spectrum can you confirm whether this is implemented on the tuner device ?

CODE
FindInterfaceInGraph(m_piGraphBuilder, IID_IBDA_SignalStatistics - FAILED !!!


Just to confirm that we are looking for the same thing from <bdaiface.h>

CODE
EXTERN_C const IID IID_IBDA_SignalStatistics;



#if defined(__cplusplus) && !defined(CINTERFACE)

   

   MIDL_INTERFACE("1347D106-CF3A-428a-A5CB-AC0D9A2A4338")

   IBDA_SignalStatistics : public IUnknown

   {
Spectrum
I know that it's implemented in code, but I'll have to wait until I get home to check if it's exposed properly. And yes - it should appear on the Tuner filter.

Spectrum
bionicdonkey
Could someone show me an example of how they created the object (CoCreateInstance) for the Tuner Device or Capture Device please.
null_pointer
You can find an example in the BDA sample:

http://www.digtv.ws/files/dvb/BDA/BDA%20Sa...le%20Ver-02.zip
bionicdonkey
Thats pretty much what i've done. What i would actually like to know is which function creates the object. I say this because when i create the Network Provide and Demux i need the CoCreateInitialise then AddFilter.
bionicdonkey
I wouldn't be BindToObject by any chance would it?
null_pointer
Yes, you use the system device enumirator and then BindToObject to get an actual usable filter. From memory that is what you do anyway :-) You still have to add it to the graph though.
Spectrum
As far as I can tell the driver code is correct.

Spectrum
null_pointer
Ok, if the driver code is correct then how do you get access to the interface. I know it most be possible but I can not get it to work :-(
bionicdonkey
Is it possible to build a function into the filter to get the info? I may be extreme, but if no one can figure out how to use signalstats class it may be needed.

Has anyone seen any other dvb forums around that develop there own software? maybe they've figure it out
Spectrum
This looks rather convoluted but follow this link and search for IID_IBDA_SignalStatistics

http://cvs.sourceforge.net/viewcvs.py/*che...ETV.CPP?rev=1.9

Spectrum
null_pointer
Ok, yes once you have something to look at it all falls into place :-)

CODE
HRESULT hr2;



    CComPtr <IBDA_Topology> bdaNetTop;

    hr2 = m_pTunerDevice.QueryInterface(&bdaNetTop);

   if (FAILED(hr2))

   {

 ErrorMessageBox(TEXT("Cannot Find IID_IBDA_Topologyn"));

    }



    CComPtr <IUnknown> unknown;



    hr2 = bdaNetTop->GetControlNode(0, 1, 1, &unknown);

   if (FAILED(hr2))

   {

 ErrorMessageBox(TEXT("Cannot GetControlNoden"));

    }



    CComPtr <IBDA_SignalStatistics> pSigStats;

    hr2 = unknown.QueryInterface(&pSigStats);

   if (FAILED(hr2))

   {

 ErrorMessageBox(TEXT("Cannot get IBDA_SignalStatisticsn"));

    }



    long quality = -1;

    hr2 = pSigStats->get_SignalQuality(&quality);

   if (FAILED(hr2))

   {

 ErrorMessageBox(TEXT("Cannot get_SignalQualityn"));

    }

    else

    {

 char buff[128];

 sprintf(buff, "Signal Quality = %d", quality);

 ErrorMessageBox(TEXT(buff));

    }


This works for me :-) to get the Quality of the signal.

Spectrum, where did you find this link, I must have done 50 searches on google looking for exactly this code.
Spectrum
I knew of the project from about 18 months ago.

http://bdadev.sourceforge.net/

Spectrum
JoeyBloggs
I've been searching for days too Null :roll:

Spectrum, Is there some reasonable way to enum the topology to get to the IBDA_SignalStatistics interface.

ie does the ExamineTuner code block in SimpleTv.cpp look viable as a way of finding the interface for other drivers ? Or is their a simpler way
Spectrum
???? Doesn't null_pointer's code above do what you are asking?

Spectrum
bionicdonkey
It works for me (with a little tweaking). But i still can't get the strength
JoeyBloggs
Ok its working for the SpectrumBDA driver. Avoid FindInterfaceInGraph as several filters implement it :?

Same as bionic though I get strength only though ITuner and Quality only through IBDA_SignalStatistics

CODE
//FindInterfaceInGraph(m_piGraphBuilder, IID_IBDA_Topology, &piBaseFilter, reinterpret_cast<void**>(&piTopology) );

 

hr = m_piTunerDeviceFilter->QueryInterface(IID_IBDA_Topology, reinterpret_cast<void**>(&piTopology) );
Spectrum
OK, it's making sense to me now.

You need to keep in mind that the whole Broadcast Driver Architecture has been written to be very flexible considering Microsoft could not know ahead of time of all of the possible permutations of hardware.

For an awfully terse introduction to control nodes read this section of the DDK docs http://msdn.microsoft.com/library/en-us/st.../bdaov_2dyf.asp

When you get to the page "Combining Nodes in a Filter" you will see a picture that is representative of the driver set I've written. The Tuner/Demodulator nodes are combined in the tuner driver and the Capture node is in the capture driver.

You get Signal Strength and Signal Present from the Tuner node, and you get Signal Quality and Signal Locked from the Demodulator node.

Define this in your code:
CODE
typedef enum {

   BDA_TWINHAN_TUNER_NODE = 0,

   BDA_TWINHAN_DEMODULATOR_NODE

} BDA_TWINHAN_NODES;


Then null_pointer's code (add your own error checking code) becomes:
CODE
hr2 = bdaNetTop->GetControlNode(0, 1, BDA_TWINHAN_DEMODULATOR_NODE, &unknown);



CComPtr <IBDA_SignalStatistics> pSigStats;

hr2 = unknown.QueryInterface(&pSigStats);



long quality = -1;

hr2 = pSigStats->get_SignalQuality(&quality);

BOOLEAN locked = FALSE;

hr2 = pSigStats->get_SignalLocked(&locked);





hr2 = bdaNetTop->GetControlNode(0, 1, BDA_TWINHAN_TUNER_NODE, &unknown2);



CComPtr <IBDA_SignalStatistics> pSigStats2;

hr2 = unknown2.QueryInterface(&pSigStats2);



long strength = -1;

hr2 = pSigStats2->get_SignalStrength(&strength);

BOOLEAN present = FALSE;

hr2 = pSigStats2->get_SignalPresent(&present);


As usual I have not tried this myself so please post your findings here.

Spectrum
JoeyBloggs
Happy to try this. But surely it can be handled inside the driver ? It's aware of it's own topography.

The whole point of BDA architecture is that my BDA application code should work with any BDA driver.
Spectrum
I realised that myself while trying to get to sleep last night :? It makes no sense to hard code values for my drivers.

It's not, however, a driver thing - you need to handle it in your code so let's find a general solution.

Spectrum
null_pointer
So this would mean that to get access to the IBDA_FrequencyFilter interface to set the bandwidth I would do the followng:

CODE
hr2 = bdaNetTop->GetControlNode(0, 1, BDA_TWINHAN_TUNER_NODE, &unknown2);



CComPtr <IBDA_FrequencyFilter> pFreqFilt;

hr2 = unknown2.QueryInterface(&pFreqFilt);



pFreqFilt->put_Bandwidth(7000);
Spectrum
OK, the generic solution is going to be a little verbose.

CODE
ULONG NodeTypes;

ULONG NodeType[32];

ULONG Interfaces;

GUID Interface[32];

ULONG SigStatsCount;

CComPtr <IBDA_SignalStatistics> ppSigStats[8];



SigStatsCount = 0;



hr2 = bdaNetTop->GetNodeTypes(&NodeTypes, 32, NodeType);



if (hr2 == S_OK) {

 for (int i = 0; i < NodeTypes; i++) {

   hr2 = bdaNetTop->GetNodeInterfaces(NodeType[i], &Interfaces, 32, Interface);

   if (hr2 == S_OK) {

     for (int j = 0; j < Interfaces; j++) {

       if (Interface[j] == IID_IBDA_SignalStatistics) { // This node implements Signal Statistics

         hr2 = bdaNetTop->GetControlNode(0, 1, NodeType[i], &unknown);

         

         hr2 = unknown.QueryInterface(&(ppSigStats[SigStatsCount]));

         if (hr2 == S_OK) {

           SigStatsCount++;

         }

       }

     }

   }

 }

}

SigStatsCount will indicate the number of nodes implementing IBDA_SignalStatistics and the COM objects will be in ppSigStats[]

As usual I have not tried this code myself.

I'd like to point out that I have implemented Signal Quality and Signal Locked on the Demodulator node and Signal Strength and Signal Present on the Tuner node. I did that because the Microsoft example code did it that way. So as it stands you will get the IBDA_SignalStatistics interface on two nodes. But I don't know how you would determine which methods are implemented on which node.

For example, would calling get_SignalQuality() on the Tuner node return an HRESULT with an error status (some kind of NOT_IMPLEMENTED)?

I could change my code so that all IBDA_SignalStatistics are implemented on one node, but other hardware vendors would still be able to split the methods among more than one node - so for robustness you may as well write your code to handle it properly.

If someone can come up with cleaner code implementation than the above then please, please, please post it :oops:

Spectrum
JoeyBloggs
I can't see any less verbose way of doing it either :? I think most people are going to follow the microsoft sample code and have two SignalStatistics interfaces. Haven't got to the point of testing them individually yet.

CODE
///////////////////////////////////////////////////////////////////////////////

void CBaseDtvTunerBDASource::ExamineTuner()

{

    HRESULT         hr                   = S_OK;



    IBDA_Topology*    piTopology           = NULL;

    IUnknown*  piUnknownNode        = NULL;

    IUnknown*  piUnknownInterface   = NULL;



    ULONG      PinTypes;

    ULONG      PinType[256];

    

    ULONG      NodeTypes;

    ULONG      NodeType[256];

    

    ULONG      Interfaces;

    GUID      Interface[256];



    if (m_piTunerDeviceFilter != NULL)

    {

 hr = m_piTunerDeviceFilter->QueryInterface(IID_IBDA_Topology, reinterpret_cast<void**>(&piTopology) );



 if (SUCCEEDED(hr))

 {

     hr = piTopology->GetPinTypes(&PinTypes, 256, PinType);

     

     if (hr == S_OK)

     {

   MYTRACE("%d pin types:n", PinTypes);

   

   for (int i = 0; i < PinTypes; i++)

   {

       MYTRACE("Pin %d = %dn", i, PinType[i]);

   };

     };



     ///////////////////////////////



     hr = piTopology->GetNodeTypes(&NodeTypes, 256, NodeType);

     

     if (SUCCEEDED(hr))

     {

   MYTRACE("%d node types:n", NodeTypes);

   

   for (int i = 0; i < NodeTypes; i++)

   {

       MYTRACE("Node %d = %dn", i, NodeType[i]);

   }

       

   MYTRACE("node interfaces:n");



   for (i = 0; i < NodeTypes; i++)

   {

       hr = piTopology->GetNodeInterfaces(NodeType[i], &Interfaces, 256, Interface);

       

       if (SUCCEEDED(hr))

       {

     hr = piTopology->GetControlNode(0, 1, NodeType[i], &piUnknownNode);



     if (SUCCEEDED(hr))

     {

         MYTRACE("NodeType %d has %d interfaces:n", i, Interfaces);

         

         for (int ii = 0; ii < Interfaces; ii++)

         {

       hr = piUnknownNode->QueryInterface(Interface[ii], reinterpret_cast<void**>(&piUnknownInterface) );



       if (hr == S_OK)

       {

           MYTRACE("Found Interface %s %sn", ClassIdToString(Interface[ii]), BDAInterfaceToName(Interface[ii]) );



           piUnknownInterface->Release();

       }

       else

       {

           MYTRACE("Found Interface %s %s - QI FAILED !!! - hr = 0x%0lxn", ClassIdToString(Interface[ii]), BDAInterfaceToName(Interface[ii]), hr );

       }

         

         } //  next interface



         piUnknownNode->Release();

     }

       }



   } //next node type



     }

 }

 else

 {

     MYTRACE("m_piTunerDeviceFilter->QueryInterface(IID_IBDA_Topology, reinterpret_cast<void**>(&piTopology) - FAILED !!!n");

 }

    }

    else

    {

 MYTRACE("m_piTunerDeviceFilter == NULL !!!n");

    }

}


CODE
///////////////////////////////////////////////////////////////////////////////

CString CBaseDtvTunerBDASource::BDAInterfaceToName(REFIID iid)

{

    CString sName = _T("");



  if (iid == IID_IBDA_NetworkProvider   ) { sName = _T("IID_IBDA_NetworkProvider   "); }

    else if (iid == IID_IBDA_EthernetFilter    ) { sName = _T("IID_IBDA_EthernetFilter    "); }

    else if (iid == IID_IBDA_IPV4Filter        ) { sName = _T("IID_IBDA_IPV4Filter        "); }

    else if (iid == IID_IBDA_IPV6Filter        ) { sName = _T("IID_IBDA_IPV6Filter        "); }

    else if (iid == IID_IBDA_DeviceControl     ) { sName = _T("IID_IBDA_DeviceControl     "); }

    else if (iid == IID_IBDA_PinControl        ) { sName = _T("IID_IBDA_PinControl        "); }

    else if (iid == IID_IBDA_SignalProperties  ) { sName = _T("IID_IBDA_SignalProperties  "); }

    else if (iid == IID_IBDA_SignalStatistics  ) { sName = _T("IID_IBDA_SignalStatistics  "); }

    else if (iid == IID_IBDA_Topology          ) { sName = _T("IID_IBDA_Topology          "); }

    else if (iid == IID_IBDA_VoidTransform     ) { sName = _T("IID_IBDA_VoidTransform     "); }

    else if (iid == IID_IBDA_NullTransform     ) { sName = _T("IID_IBDA_NullTransform     "); }

    else if (iid == IID_IBDA_FrequencyFilter   ) { sName = _T("IID_IBDA_FrequencyFilter   "); }

    else if (iid == IID_IBDA_LNBInfo           ) { sName = _T("IID_IBDA_LNBInfo           "); }

    else if (iid == IID_IBDA_AutoDemodulate    ) { sName = _T("IID_IBDA_AutoDemodulate    "); }

    else if (iid == IID_IBDA_DigitalDemodulator) { sName = _T("IID_IBDA_DigitalDemodulator"); }

    else if (iid == IID_IBDA_IPSinkControl     ) { sName = _T("IID_IBDA_IPSinkControl     "); }

    else if (iid == IID_IBDA_IPSinkInfo        ) { sName = _T("IID_IBDA_IPSinkInfo        "); }

    else if (iid == IID_IEnumPIDMap            ) { sName = _T("IID_IEnumPIDMap            "); }

    else if (iid == IID_IMPEG2PIDMap           ) { sName = _T("IID_IMPEG2PIDMap           "); }

    else if (iid == IID_IFrequencyMap          ) { sName = _T("IID_IFrequencyMap          "); }

    else                                         { sName = _T("Unknown Interface          "); }



    return sName;

}
JoeyBloggs
Ok someone else seems to return 0x80070490 "Element not found"

CODE
Node(0,1,0) Signal Strength = 0 hr = 0x0

Node(0,1,0) Signal Quality  = 0 hr = 0x80070490

Node(0,1,1) Signal Strength = 0 hr = 0x80070490

Node(0,1,1) Signal Quality  = 0 hr = 0x0
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Invision Power Board © 2001-2008 Invision Power Services, Inc.