[vlc-devel] [PATCH] BDA allow card selection

Ken Self kenself at optusnet.com.au
Sat Dec 27 11:34:08 CET 2008


---
 modules/access/bda/bda.c        |   22 ++-
 modules/access/bda/bdadefs.h    |  397 ++++++++++++++++++++++++++++++++++++++-
 modules/access/bda/bdagraph.cpp |  264 +++++++++++++++++++-------
 modules/access/bda/bdagraph.h   |   10 +-
 4 files changed, 607 insertions(+), 86 deletions(-)

diff --git a/modules/access/bda/bda.c b/modules/access/bda/bda.c
index 78080c3..f078357 100644
--- a/modules/access/bda/bda.c
+++ b/modules/access/bda/bda.c
@@ -3,7 +3,7 @@
  *****************************************************************************
  * Copyright (C) 2007 the VideoLAN team
  *
- * Author: Ken Self <kens at campoz.fslife.co.uk>
+ * Author: Ken Self <kenself(at)optusnet(dot)com(dot)au>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -191,19 +191,20 @@ vlc_module_begin ()
 
     add_integer( "dvb-caching", DEFAULT_PTS_DELAY / 1000, NULL, CACHING_TEXT,
                  CACHING_LONGTEXT, true );
-    add_integer( "dvb-frequency", 11954000, NULL, FREQ_TEXT, FREQ_LONGTEXT,
+    add_integer( "dvb-frequency", 0, NULL, FREQ_TEXT, FREQ_LONGTEXT,
                  false );
 #   if defined(WIN32) || defined(WINCE)
         add_string( "dvb-network-name", NULL, NULL, NAME_TEXT, NAME_LONGTEXT,
                     true );
         add_string( "dvb-create-name", NULL, NULL, CREATE_TEXT,
                     CREATE_LONGTEXT, true );
+        add_integer( "dvb-adapter", -1, NULL, ADAPTER_TEXT, ADAPTER_LONGTEXT,
+                     true );
 #   else
-        add_integer( "dvb-adapter", 0, NULL, ADAPTER_TEXT, ADAPTER_LONGTEXT,
-                     false );
+        /* dvb-device refers to a frontend within an adapter */
         add_integer( "dvb-device", 0, NULL, DEVICE_TEXT, DEVICE_LONGTEXT,
                      true );
-        add_bool( "dvb-probe", 1, NULL, PROBE_TEXT, PROBE_LONGTEXT, true )
+        add_bool( "dvb-probe", 1, NULL, PROBE_TEXT, PROBE_LONGTEXT, true );
         add_bool( "dvb-budget-mode", 0, NULL, BUDGET_TEXT, BUDGET_LONGTEXT,
                   true );
 #   endif
@@ -227,6 +228,8 @@ vlc_module_begin ()
             LONGITUDE_LONGTEXT, true );
         add_string( "dvb-range", NULL, NULL, RANGE_TEXT,
             RANGE_LONGTEXT, true );
+        /* dvb-range corresponds to the BDA InputRange parameter which is
+         * used by some drivers to control the diseqc */
 #   else
         add_integer( "dvb-satno", 0, NULL, SATNO_TEXT, SATNO_LONGTEXT,
             true );
@@ -311,13 +314,14 @@ static int Open( vlc_object_t *p_this )
     access_t     *p_access = (access_t*)p_this;
     access_sys_t *p_sys;
     const char* psz_module  = "dvb";
-    const int   i_param_count = 25;
+    const int   i_param_count = 26;
     const char* psz_param[] = { "frequency", "bandwidth",
         "srate", "azimuth", "elevation", "longitude", "polarisation",
         "modulation", "caching", "lnb-lof1", "lnb-lof2", "lnb-slof",
         "inversion", "network-id", "code-rate-hp", "code-rate-lp",
         "guard", "transmission", "hierarchy", "range", "network-name",
-        "create-name", "major-channel", "minor-channel", "physical-channel" };
+        "create-name", "major-channel", "minor-channel", "physical-channel",
+        "adapter" };
 
     const int   i_type[] = { VLC_VAR_INTEGER, VLC_VAR_INTEGER,
         VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER,
@@ -325,7 +329,7 @@ static int Open( vlc_object_t *p_this )
         VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER,
         VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER,
         VLC_VAR_INTEGER, VLC_VAR_STRING, VLC_VAR_STRING, VLC_VAR_STRING,
-        VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER };
+        VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER };
 
     char  psz_full_name[128];
     int i_ret;
@@ -437,7 +441,7 @@ static int ParsePath( access_t *p_access, const char* psz_module,
     i_token_len = strcspn( psz_parser, ":" );
     if( i_token_len <= 0 )
         i_token_len  = strcspn( ++psz_parser, ":" );
- 
+
     do
     {
         psz_token = strndup( psz_parser, i_token_len );
diff --git a/modules/access/bda/bdadefs.h b/modules/access/bda/bdadefs.h
index 258d0bd..c9fe2a8 100644
--- a/modules/access/bda/bdadefs.h
+++ b/modules/access/bda/bdadefs.h
@@ -3,7 +3,7 @@
  *****************************************************************************
  * Copyright (C) 2007 the VideoLAN team
  *
- * Author: Ken Self <kens at campoz.fslife.co.uk>
+ * Author: Ken Self <kenself(at)optusnet(dot)com(dot)au>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -22,6 +22,10 @@
 
 class IATSCChannelTuneRequest;
 class IATSCLocator;
+class IBDA_DeviceControl;
+class IBDA_FrequencyFilter;
+class IBDA_SignalStatistics;
+class IBDA_Topology;
 class IChannelTuneRequest;
 class IComponent;
 class IComponents;
@@ -46,6 +50,14 @@ class ITuneRequest;
 class ITuningSpace;
 class ITuningSpaceContainer;
 class ITuningSpaces;
+class IMpeg2Data;
+class IGuideData;
+class IGuideDataEvent;
+class ISectionList;
+class IEnumTuneRequests;
+class IEnumGuideDataProperties;
+class IGuideDataProperty;
+class IMpeg2Stream;
 
 typedef enum BinaryConvolutionCodeRate
 {
@@ -179,6 +191,27 @@ typedef enum TransmissionMode
     BDA_XMIT_MODE_MAX,
 } TransmissionMode;
 
+typedef struct _BDANODE_DESCRIPTOR
+{
+    ULONG               ulBdaNodeType;
+    GUID                guidFunction;
+    GUID                guidName;
+} BDANODE_DESCRIPTOR, *PBDANODE_DESCRIPTOR;
+
+typedef struct _BDA_TEMPLATE_CONNECTION
+{
+    ULONG   FromNodeType;
+    ULONG   FromNodePinType;
+    ULONG   ToNodeType;
+    ULONG   ToNodePinType;
+} BDA_TEMPLATE_CONNECTION, *PBDA_TEMPLATE_CONNECTION;
+
+typedef struct _BDA_TEMPLATE_PIN_JOINT
+{
+    ULONG   uliTemplateConnection;
+    ULONG   ulcInstancesMax;
+} BDA_TEMPLATE_PIN_JOINT, *PBDA_TEMPLATE_PIN_JOINT;
+
 class IComponent : public IDispatch
 {
 public:
@@ -284,7 +317,8 @@ public:
     virtual HRESULT __stdcall get_TuningSpace(
         ITuningSpace** p_p_tuning_space )=0;
     virtual HRESULT __stdcall put_TuningSpace( ITuningSpace* p_tuning_space )=0;
-    virtual HRESULT __stdcall EnumTuningSpaces( IEnumTuningSpaces** p_p_enum )=0;
+    virtual HRESULT __stdcall EnumTuningSpaces(
+       IEnumTuningSpaces** p_p_enum )=0;
     virtual HRESULT __stdcall get_TuneRequest(
         ITuneRequest** p_p_tune_request )=0;
     virtual HRESULT __stdcall put_TuneRequest( ITuneRequest* p_tune_request )=0;
@@ -541,6 +575,344 @@ public:
         IEnumTuningSpaces** p_p_enum )=0;
 };
 
+class IBDA_DeviceControl : public IUnknown
+{
+public:
+    virtual HRESULT __stdcall StartChanges( void )=0;
+    virtual HRESULT __stdcall CheckChanges( void )=0;
+    virtual HRESULT __stdcall CommitChanges( void )=0;
+    virtual HRESULT __stdcall GetChangeState( ULONG *pState )=0;
+};
+
+class IBDA_FrequencyFilter : public IUnknown
+{
+public:
+    virtual HRESULT __stdcall put_Autotune( ULONG ulTransponder )=0;
+    virtual HRESULT __stdcall get_Autotune( ULONG *pulTransponder )=0;
+    virtual HRESULT __stdcall put_Frequency( ULONG ulFrequency )=0;
+    virtual HRESULT __stdcall get_Frequency( ULONG *pulFrequency )=0;
+    virtual HRESULT __stdcall put_Polarity( Polarisation Polarity )=0;
+    virtual HRESULT __stdcall get_Polarity( Polarisation *pPolarity )=0;
+    virtual HRESULT __stdcall put_Range( ULONG ulRange )=0;
+    virtual HRESULT __stdcall get_Range( ULONG *pulRange )=0;
+    virtual HRESULT __stdcall put_Bandwidth( ULONG ulBandwidth )=0;
+    virtual HRESULT __stdcall get_Bandwidth( ULONG *pulBandwidth )=0;
+    virtual HRESULT __stdcall put_FrequencyMultiplier( ULONG ulMultiplier )=0;
+    virtual HRESULT __stdcall get_FrequencyMultiplier(
+        ULONG *pulMultiplier )=0;
+};
+
+class IBDA_SignalStatistics : public IUnknown
+{
+public:
+    virtual HRESULT __stdcall put_SignalStrength( LONG lDbStrength )=0;
+    virtual HRESULT __stdcall get_SignalStrength( LONG *plDbStrength )=0;
+    virtual HRESULT __stdcall put_SignalQuality( LONG lPercentQuality )=0;
+    virtual HRESULT __stdcall get_SignalQuality( LONG *plPercentQuality )=0;
+    virtual HRESULT __stdcall put_SignalPresent( BOOLEAN fPresent )=0;
+    virtual HRESULT __stdcall get_SignalPresent( BOOLEAN *pfPresent )=0;
+    virtual HRESULT __stdcall put_SignalLocked( BOOLEAN fLocked )=0;
+    virtual HRESULT __stdcall get_SignalLocked( BOOLEAN *pfLocked )=0;
+    virtual HRESULT __stdcall put_SampleTime( LONG lmsSampleTime )=0;
+    virtual HRESULT __stdcall get_SampleTime( LONG *plmsSampleTime )=0;
+};
+
+class IBDA_Topology : public IUnknown
+{
+public:
+    virtual HRESULT __stdcall GetNodeTypes( ULONG *pulcNodeTypes,
+        ULONG ulcNodeTypesMax, ULONG rgulNodeTypes[] )=0;
+    virtual HRESULT __stdcall GetNodeDescriptors( ULONG *ulcNodeDescriptors,
+        ULONG ulcNodeDescriptorsMax,
+        BDANODE_DESCRIPTOR rgNodeDescriptors[] )=0;
+    virtual HRESULT __stdcall GetNodeInterfaces( ULONG ulNodeType,
+        ULONG *pulcInterfaces, ULONG ulcInterfacesMax,
+        GUID rgguidInterfaces[] )=0;
+    virtual HRESULT __stdcall GetPinTypes( ULONG *pulcPinTypes,
+        ULONG ulcPinTypesMax, ULONG rgulPinTypes[] )=0;
+    virtual HRESULT __stdcall GetTemplateConnections( ULONG *pulcConnections,
+        ULONG ulcConnectionsMax, BDA_TEMPLATE_CONNECTION rgConnections[] )=0;
+    virtual HRESULT __stdcall CreatePin( ULONG ulPinType, ULONG *pulPinId )=0;
+    virtual HRESULT __stdcall DeletePin( ULONG ulPinId )=0;
+    virtual HRESULT __stdcall SetMediaType( ULONG ulPinId,
+       AM_MEDIA_TYPE *pMediaType )=0;
+    virtual HRESULT __stdcall SetMedium( ULONG ulPinId,
+       REGPINMEDIUM *pMedium )=0;
+    virtual HRESULT __stdcall CreateTopology( ULONG ulInputPinId,
+       ULONG ulOutputPinId )=0;
+    virtual HRESULT __stdcall GetControlNode( ULONG ulInputPinId,
+        ULONG ulOutputPinId, ULONG ulNodeType, IUnknown **ppControlNode )=0;
+};
+
+typedef struct _MPEG_HEADER_BITS_MIDL
+{
+    WORD Bits;
+} MPEG_HEADER_BITS_MIDL;
+
+typedef struct _MPEG_HEADER_VERSION_BITS_MIDL
+{
+    BYTE Bits;
+} MPEG_HEADER_VERSION_BITS_MIDL;
+
+typedef WORD PID;
+
+typedef BYTE TID;
+
+typedef struct _SECTION
+{
+    TID TableId;
+    union
+    {
+        MPEG_HEADER_BITS_MIDL S;
+        WORD W;
+    } Header;
+    BYTE SectionData[ 1 ];
+} SECTION, *PSECTION;
+
+typedef struct _LONG_SECTION
+{
+    TID TableId;
+    union
+    {
+        MPEG_HEADER_BITS_MIDL S;
+        WORD W;
+    } Header;
+    WORD TableIdExtension;
+    union
+    {
+        MPEG_HEADER_VERSION_BITS_MIDL S;
+        BYTE B;
+        } Version;
+    BYTE SectionNumber;
+    BYTE LastSectionNumber;
+    BYTE RemainingData[ 1 ];
+} LONG_SECTION;
+
+typedef struct _MPEG_BCS_DEMUX
+{
+    DWORD AVMGraphId;
+} MPEG_BCS_DEMUX;
+
+typedef struct _MPEG_WINSOC
+{
+    DWORD AVMGraphId;
+} MPEG_WINSOCK;
+
+typedef enum
+{
+    MPEG_CONTEXT_BCS_DEMUX = 0,
+    MPEG_CONTEXT_WINSOCK = MPEG_CONTEXT_BCS_DEMUX + 1
+} MPEG_CONTEXT_TYPE;
+
+typedef struct _MPEG_RQST_PACKET
+{
+    DWORD dwLength;
+    PSECTION pSection;
+} MPEG_RQST_PACKET, *PMPEG_RQST_PACKET;
+
+typedef struct _MPEG_PACKET_LIST
+{
+    WORD wPacketCount;
+    PMPEG_RQST_PACKET PacketList[ 1 ];
+} MPEG_PACKET_LIST, *PMPEG_PACKET_LIST;
+
+typedef struct _DSMCC_FILTER_OPTIONS
+{
+    BOOL fSpecifyProtocol;
+    BYTE Protocol;
+    BOOL fSpecifyType;
+    BYTE Type;
+    BOOL fSpecifyMessageId;
+    WORD MessageId;
+    BOOL fSpecifyTransactionId;
+    BOOL fUseTrxIdMessageIdMask;
+    DWORD TransactionId;
+    BOOL fSpecifyModuleVersion;
+    BYTE ModuleVersion;
+    BOOL fSpecifyBlockNumber;
+    WORD BlockNumber;
+    BOOL fGetModuleCall;
+    WORD NumberOfBlocksInModule;
+} DSMCC_FILTER_OPTIONS;
+
+typedef struct _ATSC_FILTER_OPTIONS
+{
+    BOOL fSpecifyEtmId;
+    DWORD EtmId;
+} ATSC_FILTER_OPTIONS;
+
+typedef struct _MPEG_STREAM_BUFFER
+{
+    HRESULT hr;
+    DWORD dwDataBufferSize;
+    DWORD dwSizeOfDataRead;
+    BYTE *pDataBuffer;
+} MPEG_STREAM_BUFFER, *PMPEG_STREAM_BUFFER;
+
+typedef struct _MPEG_CONTEXT
+{
+    MPEG_CONTEXT_TYPE Type;
+    union
+    {
+        MPEG_BCS_DEMUX Demux;
+        MPEG_WINSOCK Winsock;
+    } U;
+} MPEG_CONTEXT, *PMPEG_CONTEXT;
+
+typedef enum
+{
+   MPEG_RQST_UNKNOWN = 0,
+   MPEG_RQST_GET_SECTION = MPEG_RQST_UNKNOWN + 1,
+   MPEG_RQST_GET_SECTION_ASYNC = MPEG_RQST_GET_SECTION + 1,
+   MPEG_RQST_GET_TABLE = MPEG_RQST_GET_SECTION_ASYNC + 1,
+   MPEG_RQST_GET_TABLE_ASYNC = MPEG_RQST_GET_TABLE + 1,
+   MPEG_RQST_GET_SECTIONS_STREAM = MPEG_RQST_GET_TABLE_ASYNC + 1,
+   MPEG_RQST_GET_PES_STREAM = MPEG_RQST_GET_SECTIONS_STREAM + 1,
+   MPEG_RQST_GET_TS_STREAM = MPEG_RQST_GET_PES_STREAM + 1,
+   MPEG_RQST_START_MPE_STREAM = MPEG_RQST_GET_TS_STREAM + 1
+} MPEG_REQUEST_TYPE;
+
+typedef struct _MPEG2_FILTER
+{
+    BYTE bVersionNumber;
+    WORD wFilterSize;
+    BOOL fUseRawFilteringBits;
+    BYTE Filter[ 16 ];
+    BYTE Mask[ 16 ];
+    BOOL fSpecifyTableIdExtension;
+    WORD TableIdExtension;
+    BOOL fSpecifyVersion;
+    BYTE Version;
+    BOOL fSpecifySectionNumber;
+    BYTE SectionNumber;
+    BOOL fSpecifyCurrentNext;
+    BOOL fNext;
+    BOOL fSpecifyDsmccOptions;
+    DSMCC_FILTER_OPTIONS Dsmcc;
+    BOOL fSpecifyAtscOptions;
+    ATSC_FILTER_OPTIONS Atsc;
+} MPEG2_FILTER, *PMPEG2_FILTER;
+
+typedef struct _MPEG_HEADER_BITS
+{
+    WORD SectionLength          : 12;
+    WORD Reserved               :  2;
+    WORD PrivateIndicator       :  1;
+    WORD SectionSyntaxIndicator :  1;
+} MPEG_HEADER_BITS, *PMPEG_HEADER_BITS;
+
+typedef struct _MPEG_HEADER_VERSION_BITS
+{
+    BYTE CurrentNextIndicator : 1;
+    BYTE VersionNumber        : 5;
+    BYTE Reserved             : 2;
+} MPEG_HEADER_VERSION_BITS, *PMPEG_HEADER_VERSION_BITS;
+
+class IMpeg2Data : public IUnknown
+{
+public:
+    virtual HRESULT __stdcall GetSection( PID pid, TID tid,
+        PMPEG2_FILTER pFilter, DWORD dwTimeout,
+        ISectionList **ppSectionList )=0;
+    virtual HRESULT __stdcall GetTable( PID pid, TID tid, PMPEG2_FILTER pFilter,
+        DWORD dwTimeout, ISectionList **ppSectionList )=0;
+    virtual HRESULT __stdcall GetStreamOfSections( PID pid, TID tid,
+        PMPEG2_FILTER pFilter, HANDLE hDataReadyEvent,
+        IMpeg2Stream **ppMpegStream )=0;
+};
+
+class IGuideData : public IUnknown
+{
+public:
+    virtual HRESULT __stdcall GetServices(
+        IEnumTuneRequests **ppEnumTuneRequestslass )=0;
+    virtual HRESULT __stdcall GetServiceProperties(
+        ITuneRequest *pTuneRequest,
+        IEnumGuideDataProperties **ppEnumProperties )=0;
+    virtual HRESULT __stdcall GetGuideProgramIDs(
+        IEnumVARIANT **pEnumPrograms )=0;
+    virtual HRESULT __stdcall GetProgramProperties(
+        VARIANT varProgramDescriptionID,
+        IEnumGuideDataProperties **ppEnumProperties )=0;
+    virtual HRESULT __stdcall GetScheduleEntryIDs(
+        IEnumVARIANT **pEnumScheduleEntries )=0;
+    virtual HRESULT __stdcall GetScheduleEntryProperties(
+        VARIANT varScheduleEntryDescriptionID,
+        IEnumGuideDataProperties **ppEnumProperties )=0;
+};
+
+class IGuideDataEvent : public IUnknown
+{
+public:
+    virtual HRESULT __stdcall GuideDataAcquired( void )=0;
+    virtual HRESULT __stdcall ProgramChanged(
+        VARIANT varProgramDescriptionID )=0;
+    virtual HRESULT __stdcall ServiceChanged(
+        VARIANT varServiceDescriptionID )=0;
+    virtual HRESULT __stdcall ScheduleEntryChanged(
+        VARIANT varScheduleEntryDescriptionID )=0;
+    virtual HRESULT __stdcall ProgramDeleted(
+        VARIANT varProgramDescriptionID )=0;
+    virtual HRESULT __stdcall ServiceDeleted(
+        VARIANT varServiceDescriptionID )=0;
+    virtual HRESULT __stdcall ScheduleDeleted(
+            VARIANT varScheduleEntryDescriptionID )=0;
+};
+
+class IGuideDataProperty : public IUnknown
+{
+public:
+    virtual  HRESULT __stdcall get_Name( BSTR *pbstrName )=0;
+    virtual  HRESULT __stdcall get_Language( long *idLang )=0;
+    virtual  HRESULT __stdcall get_Value( VARIANT *pvar )=0;
+};
+
+class IMpeg2Stream : public IUnknown
+{
+public:
+    virtual HRESULT __stdcall Initialize( MPEG_REQUEST_TYPE requestType,
+        IMpeg2Data *pMpeg2Data, PMPEG_CONTEXT pContext, PID pid, TID tid,
+        PMPEG2_FILTER pFilter, HANDLE hDataReadyEvent )=0;
+    virtual HRESULT __stdcall SupplyDataBuffer(
+        PMPEG_STREAM_BUFFER pStreamBuffer )=0;
+};
+
+class ISectionList : public IUnknown
+{
+public:
+    virtual HRESULT __stdcall Initialize( MPEG_REQUEST_TYPE requestType,
+        IMpeg2Data *pMpeg2Data, PMPEG_CONTEXT pContext, PID pid, TID tid,
+        PMPEG2_FILTER pFilter, DWORD timeout, HANDLE hDoneEvent )=0;
+    virtual HRESULT __stdcall InitializeWithRawSections(
+        PMPEG_PACKET_LIST pmplSections )=0;
+    virtual HRESULT __stdcall CancelPendingRequest( void )=0;
+    virtual HRESULT __stdcall GetNumberOfSections( WORD *pCount )=0;
+    virtual HRESULT __stdcall GetSectionData( WORD sectionNumber,
+        DWORD *pdwRawPacketLength, PSECTION *ppSection )=0;
+    virtual HRESULT __stdcall GetProgramIdentifier( PID *pPid )=0;
+    virtual HRESULT __stdcall GetTableIdentifier( TID *pTableId )=0;
+};
+
+class IEnumGuideDataProperties : public IUnknown
+{
+public:
+    virtual HRESULT __stdcall Next( unsigned long celt,
+        IGuideDataProperty **ppprop, unsigned long *pcelt )=0;
+    virtual HRESULT __stdcall Skip( unsigned long celt )=0;
+    virtual HRESULT __stdcall Reset( void )=0;
+    virtual HRESULT __stdcall Clone( IEnumGuideDataProperties **ppenum )=0;
+};
+
+class IEnumTuneRequests : public IUnknown
+{
+public:
+    virtual HRESULT __stdcall Next( unsigned long celt, ITuneRequest **ppprop,
+        unsigned long *pcelt )=0;
+    virtual HRESULT __stdcall Skip( unsigned long celt )=0;
+    virtual HRESULT __stdcall Reset( void )=0;
+    virtual HRESULT __stdcall Clone( IEnumTuneRequests **ppenum )=0;
+};
+
 extern "C" {
 extern const GUID CLSID_ATSCLocator;
 extern const GUID CLSID_ATSCNetworkProvider;
@@ -564,6 +936,13 @@ extern const GUID CLSID_SystemTuningSpaces;
 extern const GUID IID_IATSCChannelTuneRequest;
 extern const GUID IID_IATSCLocator;
 extern const GUID IID_IBaseFilter;
+extern const GUID IID_IBDA_DeviceControl;
+extern const GUID IID_IBDA_FrequencyFilter;
+extern const GUID IID_IBDA_SignalStatistics;
+/* Following symbol does not exist in library
+extern const GUID IID_IBDA_Topology; */
+const GUID IID_IBDA_Topology =
+    {0x79B56888,0x7FEA,0x4690,{0xB4,0x5D,0x38,0xFD,0x3C,0x78,0x49,0xBE}};
 extern const GUID IID_ICreateDevEnum;
 extern const GUID IID_IDVBTLocator;
 extern const GUID IID_IDVBCLocator;
@@ -580,6 +959,17 @@ extern const GUID IID_IScanningTuner;
 extern const GUID IID_ITuner;
 extern const GUID IID_ITuningSpace;
 extern const GUID IID_ITuningSpaceContainer;
+/* Following symbol does not exist in library
+extern const GUID IID_IMpeg2Data; */
+const GUID IID_IMpeg2Data =
+    {0x9B396D40,0xF380,0x4e3c,{0xA5,0x14,0x1A,0x82,0xBF,0x6E,0xBF,0xE6}};
+extern const GUID IID_IGuideData;
+extern const GUID IID_ISectionList;
+extern const GUID IID_IEnumTuneRequests;
+extern const GUID IID_IEnumGuideDataProperties;
+extern const GUID IID_IGuideDataProperty;
+extern const GUID IID_IMpeg2Stream;
+extern const GUID IID_IGuideDataEvent;
 
 extern const GUID MEDIATYPE_MPEG2_SECTIONS;
 extern const GUID MEDIASUBTYPE_None;
@@ -591,4 +981,7 @@ const GUID KSCATEGORY_BDA_RECEIVER_COMPONENT    =
     {0xFD0A5AF4,0xB41D,0x11d2,{0x9c,0x95,0x00,0xc0,0x4f,0x79,0x71,0xe0}};
 const GUID KSCATEGORY_BDA_NETWORK_TUNER         =
     {0x71985f48,0x1ca1,0x11d3,{0x9c,0xc8,0x00,0xc0,0x4f,0x79,0x71,0xe0}};
+const GUID KSDATAFORMAT_SUBTYPE_BDA_MPEG2_TRANSPORT =
+    {0xF4AEB342,0x0329,0x4fdd,{0xA8,0xFD,0x4A,0xFF,0x49,0x26,0xC9,0x78}};
+
 };
diff --git a/modules/access/bda/bdagraph.cpp b/modules/access/bda/bdagraph.cpp
index ff81677..178ff1c 100644
--- a/modules/access/bda/bdagraph.cpp
+++ b/modules/access/bda/bdagraph.cpp
@@ -3,7 +3,7 @@
  *****************************************************************************
  * Copyright( C ) 2007 the VideoLAN team
  *
- * Author: Ken Self <kens at campoz.fslife.co.uk>
+ * Author: Ken Self <kenself(at)optusnet(dot)com(dot)au>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -781,10 +781,10 @@ HRESULT BDAGraph::CreateTuneRequest()
             bstr_name(NULL) {};
         ~localComPtr()
         {
-            if( p_tuning_space_container )
-                p_tuning_space_container->Release();
             if( p_tuning_space_enum )
                 p_tuning_space_enum->Release();
+            if( p_tuning_space_container )
+                p_tuning_space_container->Release();
             if( p_this_tuning_space )
                 p_this_tuning_space->Release();
             SysFreeString( bstr_name );
@@ -840,15 +840,20 @@ HRESULT BDAGraph::CreateTuneRequest()
             }
         }
         /* else */
-        p_tuning_space->Release();
+        if( p_tuning_space )
+            p_tuning_space->Release();
+        if( p_tune_request )
+            p_tune_request->Release();
         p_tuning_space = NULL;
+        p_tune_request = NULL;
     }
 
     /* Force use of the first available Tuner Device during Build */
     l_tuner_used = -1;
 
     /* Get the SystemTuningSpaces container to enumerate through all the
-     * defined tuning spaces */
+     * defined tuning spaces.
+     * l.p_tuning_space_container->Refcount = 1  */
     hr = ::CoCreateInstance( CLSID_SystemTuningSpaces, 0, CLSCTX_INPROC,
         IID_ITuningSpaceContainer, (void**)&l.p_tuning_space_container );
     if( FAILED( hr ) )
@@ -858,6 +863,10 @@ HRESULT BDAGraph::CreateTuneRequest()
         return hr;
     }
 
+    /* Get the SystemTuningSpaces container to enumerate through all the
+     * defined tuning spaces.
+     * l.p_tuning_space_container->Refcount = 2
+     * l.p_tuning_space_enum->Refcount = 1  */
     hr = l.p_tuning_space_container->get_EnumTuningSpaces(
          &l.p_tuning_space_enum );
     if( FAILED( hr ) )
@@ -867,9 +876,17 @@ HRESULT BDAGraph::CreateTuneRequest()
         return hr;
     }
 
-    while( l.p_tuning_space_enum->Next( 1, &l.p_this_tuning_space, NULL ) ==
-        S_OK )
+    do
     {
+        /* l.p_this_tuning_space->RefCount = 1 after the first pass
+         * Release before overwriting with Next */
+        if( l.p_this_tuning_space )
+            l.p_this_tuning_space->Release();
+        l.p_this_tuning_space = NULL;
+
+        hr = l.p_tuning_space_enum->Next( 1, &l.p_this_tuning_space, NULL );
+        if( hr != S_OK ) break;
+
         hr = l.p_this_tuning_space->get__NetworkType( &guid_this_network_type );
 
         /* GUID_NULL means a non-BDA network was found e.g analog
@@ -878,6 +895,8 @@ HRESULT BDAGraph::CreateTuneRequest()
 
         if( guid_this_network_type == guid_network_type )
         {
+            /* QueryInterface to clone l.p_this_tuning_space
+             * l.p_this_tuning_space->RefCount = 2 */
             hr = l.p_this_tuning_space->QueryInterface( IID_ITuningSpace,
                 (void**)&p_tuning_space );
             if( FAILED( hr ) )
@@ -901,15 +920,22 @@ HRESULT BDAGraph::CreateTuneRequest()
             {
                 msg_Dbg( p_access, "CreateTuneRequest: Using Tuning Space: %S",
                     l.bstr_name );
+            /* CreateTuneRequest adds TuneRequest to p_tuning_space
+             * p_tune_request->RefCount = 1 */
                 hr = p_tuning_space->CreateTuneRequest( &p_tune_request );
                 if( FAILED( hr ) )
                     msg_Warn( p_access, "CreateTuneRequest: "\
                         "Cannot Create Tune Request: hr=0x%8lx", hr );
                 return hr;
             }
+            if( p_tuning_space )
+                p_tuning_space->Release();
+            p_tuning_space = NULL;
         }
     }
-    /* No tune request was found. If the create-name parameter was set then
+    while( true );
+
+    /* No tuning space was found. If the create-name parameter was set then
      * create a tuning space. By rights should use the same name used in
      * network-name
      * Also would be nice to copy a tuning space but we only come here if we do
@@ -951,8 +977,10 @@ HRESULT BDAGraph::CreateTuneRequest()
         msg_Dbg( p_access, "CreateTuneRequest: Create Tuning Space: %S",
              l.bstr_name );
     }
+
     hr = ::CoCreateInstance( cls_tuning_space, 0, CLSCTX_INPROC,
          IID_ITuningSpace, (void**)&p_tuning_space );
+
     if( FAILED( hr ) )
         msg_Warn( p_access, "CreateTuneRequest: "\
             "Cannot CoCreate new TuningSpace: hr=0x%8lx", hr );
@@ -971,18 +999,24 @@ HRESULT BDAGraph::CreateTuneRequest()
     if( FAILED( hr ) )
         msg_Warn( p_access, "CreateTuneRequest: "\
             "Cannot Put Friendly Name: hr=0x%8lx", hr );
+
     if( SUCCEEDED( hr ) )
         hr = l.p_tuning_space_container->Add( p_tuning_space, &var_id );
+
     if( FAILED( hr ) )
     {
         msg_Warn( p_access, "CreateTuneRequest: "\
             "Cannot Create new TuningSpace: hr=0x%8lx", hr );
         return hr;
     }
+    msg_Dbg( p_access, "CreateTuneRequest: Tuning Space: %S created",
+         l.bstr_name );
+
     hr = p_tuning_space->CreateTuneRequest( &p_tune_request );
     if( FAILED( hr ) )
         msg_Warn( p_access, "CreateTuneRequest: "\
             "Cannot Create Tune Request: hr=0x%8lx", hr );
+
     return hr;
 }
 
@@ -1094,7 +1128,18 @@ HRESULT BDAGraph::Build()
     }
 
     /* Add the Network Tuner to the Network Provider. On subsequent calls,
-     * l_tuner_used will cause a different tuner to be selected */
+     * l_tuner_used will cause a different tuner to be selected
+     * To select a specific device first get the parameter that nominates the
+     * device (dvb-adapter) and use the value to initialise l_tuner_used.
+     * When FindFilter returns check the contents of l_tuner_used.
+     * If it is not what was selected then the requested device was not
+     * available so return with an error. */
+
+    long l_adapter = -1;
+    l_adapter = var_GetInteger( p_access, "dvb-adapter" );
+    if( l_tuner_used < 0 && l_adapter >= 0 )
+        l_tuner_used = l_adapter - 1;
+
     hr = FindFilter( KSCATEGORY_BDA_NETWORK_TUNER, &l_tuner_used,
         p_network_provider, &p_tuner_device );
     if( FAILED( hr ) )
@@ -1104,6 +1149,13 @@ HRESULT BDAGraph::Build()
             "hr=0x%8lx", hr );
         return hr;
     }
+    if( l_adapter > 0 && l_tuner_used != l_adapter )
+    {
+         msg_Warn( p_access, "Build: "\
+             "Tuner device %d is not available", l_adapter );
+        return E_FAIL;
+    }
+    msg_Dbg( p_access, "BDAGraph: Using adapter %d", l_tuner_used );
 
     /* Always look for all capture devices to match the Network Tuner */
     l_capture_used = -1;
@@ -1119,6 +1171,9 @@ HRESULT BDAGraph::Build()
             "Cannot find Capture device. Connecting to tuner: hr=0x%8lx", hr );
     }
 
+    if( p_sample_grabber )
+         p_sample_grabber->Release();
+    p_sample_grabber = NULL;
     /* Insert the Sample Grabber to tap into the Transport Stream. */
     hr = ::CoCreateInstance( CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,
         IID_IBaseFilter, (void**)&p_sample_grabber );
@@ -1136,6 +1191,9 @@ HRESULT BDAGraph::Build()
         return hr;
     }
 
+    if( p_grabber )
+        p_grabber->Release();
+    p_grabber = NULL;
     hr = p_sample_grabber->QueryInterface( IID_ISampleGrabber,
         (void**)&p_grabber );
     if( FAILED( hr ) )
@@ -1155,6 +1213,7 @@ HRESULT BDAGraph::Build()
             "Cannot set media type on grabber filter: hr=0x%8lx", hr );
         return hr;
     }
+
     hr = Connect( p_capture_device, p_sample_grabber );
     if( FAILED( hr ) )
     {
@@ -1232,6 +1291,9 @@ HRESULT BDAGraph::Build()
     }
 
     /* The Media Control is used to Run and Stop the Graph */
+    if( p_media_control )
+        p_media_control->Release();
+    p_media_control = NULL;
     hr = p_filter_graph->QueryInterface( IID_IMediaControl,
         (void**)&p_media_control );
     if( FAILED( hr ) )
@@ -1273,14 +1335,14 @@ HRESULT BDAGraph::FindFilter( REFCLSID clsid, long* i_moniker_used,
             { ::VariantInit(&var_bstr); };
         ~localComPtr()
         {
+            if( p_property_bag )
+                p_property_bag->Release();
+            if( p_filter )
+                p_filter->Release();
             if( p_moniker )
                 p_moniker->Release();
             if( p_moniker_enum )
                 p_moniker_enum->Release();
-            if( p_filter )
-                p_filter->Release();
-            if( p_property_bag )
-                p_property_bag->Release();
             ::VariantClear(&var_bstr);
         }
     } l;
@@ -1305,27 +1367,38 @@ HRESULT BDAGraph::FindFilter( REFCLSID clsid, long* i_moniker_used,
             "Cannot CreateClassEnumerator: hr=0x%8lx", hr );
         return E_FAIL;
     }
-    while( l.p_moniker_enum->Next( 1, &l.p_moniker, 0 ) == S_OK )
+
+    do
     {
+        /* We are overwriting l.p_moniker so we should Release and nullify
+         * It is important that p_moniker and p_property_bag are fully released
+         * l.p_filter may not be dereferenced so we could force to NULL */
+        if( l.p_property_bag )
+            l.p_property_bag->Release();
+        l.p_property_bag = NULL;
+        if( l.p_filter )
+            l.p_filter->Release();
+        l.p_filter = NULL;
+        if( l.p_moniker )
+            l.p_moniker->Release();
+         l.p_moniker = NULL;
+
+        hr = l.p_moniker_enum->Next( 1, &l.p_moniker, 0 );
+        if( hr != S_OK ) break;
         i_moniker_index++;
 
         /* Skip over devices already found on previous calls */
         if( i_moniker_index <= *i_moniker_used ) continue;
         *i_moniker_used = i_moniker_index;
 
+        /* l.p_filter is Released at the top of the loop */
         hr = l.p_moniker->BindToObject( NULL, NULL, IID_IBaseFilter,
             (void**)&l.p_filter );
         if( FAILED( hr ) )
         {
-            if( l.p_moniker )
-                l.p_moniker->Release();
-            l.p_moniker = NULL;
-            if( l.p_filter)
-                 l.p_filter->Release();
-            l.p_filter = NULL;
             continue;
         }
-
+        /* l.p_property_bag is released at the top of the loop */
         hr = l.p_moniker->BindToStorage( NULL, NULL, IID_IPropertyBag,
             (void**)&l.p_property_bag );
         if( FAILED( hr ) )
@@ -1334,7 +1407,6 @@ HRESULT BDAGraph::FindFilter( REFCLSID clsid, long* i_moniker_used,
                 "Cannot Bind to Property Bag: hr=0x%8lx", hr );
             return hr;
         }
-
         hr = l.p_property_bag->Read( L"FriendlyName", &l.var_bstr, NULL );
         if( FAILED( hr ) )
         {
@@ -1354,6 +1426,7 @@ HRESULT BDAGraph::FindFilter( REFCLSID clsid, long* i_moniker_used,
         hr = Connect( p_upstream, l.p_filter );
         if( SUCCEEDED( hr ) )
         {
+            /* p_p_downstream has not been touched yet so no release needed */
             msg_Dbg( p_access, "FindFilter: Connected %S", l.var_bstr.bstrVal );
             l.p_filter->QueryInterface( IID_IBaseFilter,
                 (void**)p_p_downstream );
@@ -1368,13 +1441,8 @@ HRESULT BDAGraph::FindFilter( REFCLSID clsid, long* i_moniker_used,
             return hr;
         }
 
-        if( l.p_moniker )
-            l.p_moniker->Release();
-        l.p_moniker = NULL;
-        if( l.p_filter)
-            l.p_filter->Release();
-        l.p_filter = NULL;
     }
+    while( true );
 
     hr = E_FAIL;
     msg_Warn( p_access, "FindFilter: No filter connected: hr=0x%8lx", hr );
@@ -1400,21 +1468,20 @@ HRESULT BDAGraph::Connect( IBaseFilter* p_upstream, IBaseFilter* p_downstream )
             p_pin_temp(NULL) { };
         ~localComPtr()
         {
-            if( p_pin_upstream )
-                p_pin_upstream->Release();
+            if( p_pin_temp )
+                p_pin_temp->Release();
             if( p_pin_downstream )
                 p_pin_downstream->Release();
-            if( p_pin_upstream_enum )
-                p_pin_upstream_enum->Release();
+            if( p_pin_upstream )
+                p_pin_upstream->Release();
             if( p_pin_downstream_enum )
                 p_pin_downstream_enum->Release();
-            if( p_pin_temp )
-                p_pin_temp->Release();
+            if( p_pin_upstream_enum )
+                p_pin_upstream_enum->Release();
         }
     } l;
 
-    PIN_INFO            pin_info_upstream;
-    PIN_INFO            pin_info_downstream;
+    PIN_DIRECTION pin_dir;
 
     hr = p_upstream->EnumPins( &l.p_pin_upstream_enum );
     if( FAILED( hr ) )
@@ -1423,26 +1490,36 @@ HRESULT BDAGraph::Connect( IBaseFilter* p_upstream, IBaseFilter* p_downstream )
             "Cannot get upstream filter enumerator: hr=0x%8lx", hr );
         return hr;
     }
-    while( l.p_pin_upstream_enum->Next( 1, &l.p_pin_upstream, 0 ) == S_OK )
+
+    do
     {
-        hr = l.p_pin_upstream->QueryPinInfo( &pin_info_upstream );
+        /* Release l.p_pin_upstream before next iteration */
+        if( l.p_pin_upstream  )
+            l.p_pin_upstream ->Release();
+        l.p_pin_upstream = NULL;
+        hr = l.p_pin_upstream_enum->Next( 1, &l.p_pin_upstream, 0 );
+        if( hr != S_OK ) break;
+
+        hr = l.p_pin_upstream->QueryDirection( &pin_dir );
         if( FAILED( hr ) )
         {
             msg_Warn( p_access, "Connect: "\
-                "Cannot get upstream filter pin information: hr=0x%8lx", hr );
+                "Cannot get upstream filter pin direction: hr=0x%8lx", hr );
             return hr;
         }
         hr = l.p_pin_upstream->ConnectedTo( &l.p_pin_downstream );
-        if( hr == S_OK )
+        if( SUCCEEDED( hr ) )
+        {
             l.p_pin_downstream->Release();
-        if(FAILED( hr ) && hr != VFW_E_NOT_CONNECTED )
+            l.p_pin_downstream = NULL;
+        }
+        if( FAILED( hr ) && hr != VFW_E_NOT_CONNECTED )
         {
             msg_Warn( p_access, "Connect: "\
                 "Cannot check upstream filter connection: hr=0x%8lx", hr );
             return hr;
         }
-        if(( pin_info_upstream.dir == PINDIR_OUTPUT ) &&
-           ( hr == VFW_E_NOT_CONNECTED ) )
+        if( ( pin_dir == PINDIR_OUTPUT ) && ( hr == VFW_E_NOT_CONNECTED ) )
         {
             /* The upstream pin is not yet connected so check each pin on the
              * downstream filter */
@@ -1453,19 +1530,33 @@ HRESULT BDAGraph::Connect( IBaseFilter* p_upstream, IBaseFilter* p_downstream )
                     "downstream filter enumerator: hr=0x%8lx", hr );
                 return hr;
             }
-            while( l.p_pin_downstream_enum->Next( 1, &l.p_pin_downstream, 0 )
-                == S_OK )
+            do
             {
-                hr = l.p_pin_downstream->QueryPinInfo( &pin_info_downstream );
+                /* Release l.p_pin_downstream before next iteration */
+                if( l.p_pin_downstream  )
+                    l.p_pin_downstream ->Release();
+                l.p_pin_downstream = NULL;
+
+                hr = l.p_pin_downstream_enum->Next( 1, &l.p_pin_downstream, 0 );
+                if( hr != S_OK ) break;
+
+                hr = l.p_pin_downstream->QueryDirection( &pin_dir );
                 if( FAILED( hr ) )
                 {
                     msg_Warn( p_access, "Connect: Cannot get "\
-                        "downstream filter pin information: hr=0x%8lx", hr );
+                        "downstream filter pin direction: hr=0x%8lx", hr );
                     return hr;
                 }
 
+                /* Looking for a free Pin to connect to
+                 * A connected Pin may have an reference count > 1
+                 * so Release and nullify the pointer */
                 hr = l.p_pin_downstream->ConnectedTo( &l.p_pin_temp );
-                if( hr == S_OK ) l.p_pin_temp->Release();
+                if( SUCCEEDED( hr ) )
+                {
+                    l.p_pin_temp->Release();
+                    l.p_pin_temp = NULL;
+                }
                 if( hr != VFW_E_NOT_CONNECTED )
                 {
                     if( FAILED( hr ) )
@@ -1475,32 +1566,39 @@ HRESULT BDAGraph::Connect( IBaseFilter* p_upstream, IBaseFilter* p_downstream )
                         return hr;
                     }
                 }
-                if(( pin_info_downstream.dir == PINDIR_INPUT ) &&
-                   ( hr == VFW_E_NOT_CONNECTED ) )
+                if( ( pin_dir == PINDIR_INPUT ) &&
+                    ( hr == VFW_E_NOT_CONNECTED ) )
                 {
                     hr = p_filter_graph->ConnectDirect( l.p_pin_upstream,
                         l.p_pin_downstream, NULL );
                     if( SUCCEEDED( hr ) )
                     {
-                        pin_info_downstream.pFilter->Release();
-                        pin_info_upstream.pFilter->Release();
+                        /* If we arrive here then we have a matching pair of
+                         * pins. */
                         return S_OK;
                     }
                 }
-                /* If we fall out here it means this downstream pin was not
-                 * suitable so try the next downstream pin */
-                l.p_pin_downstream = NULL;
-                pin_info_downstream.pFilter->Release();
+                /* If we arrive here it means this downstream pin is not
+                 * suitable so try the next downstream pin.
+                 * l.p_pin_downstream is released at the top of the loop */
             }
+            while( true );
+            /* If we arrive here then we ran out of pins before we found a
+             * suitable one. Release outstanding refcounts */
+            if( l.p_pin_downstream_enum )
+                l.p_pin_downstream_enum->Release();
+            l.p_pin_downstream_enum = NULL;
+            if( l.p_pin_downstream )
+                l.p_pin_downstream->Release();
+            l.p_pin_downstream = NULL;
         }
-
-        /* If we fall out here it means we did not find any suitable downstream
-         * pin so try the next upstream pin */
-        l.p_pin_upstream = NULL;
-        pin_info_upstream.pFilter->Release();
+        /* If we arrive here it means this upstream pin is not suitable
+         * so try the next upstream pin
+         * l.p_pin_upstream is released at the top of the loop */
     }
-
-    /* If we fall out here it means we did not find any pair of suitable pins */
+    while( true );
+    /* If we arrive here it means we did not find any pair of suitable pins
+     * Outstanding refcounts are released in the destructor */
     return E_FAIL;
 }
 
@@ -1633,10 +1731,34 @@ STDMETHODIMP BDAGraph::BufferCB( double d_time, BYTE* p_buffer,
 HRESULT BDAGraph::Destroy()
 {
     HRESULT hr = S_OK;
+    ULONG ul_refcount = 0;
 
     if( p_media_control )
         hr = p_media_control->Stop();
 
+    if( d_graph_register )
+    {
+        Deregister();
+    }
+
+/* We need to empty the buffers of any unprocessed data */
+    msg_Dbg( p_access, "Queue sample size = %d", queue_sample.size() );
+    while( !queue_sample.empty() )
+    {
+        ul_refcount = queue_sample.front()->Release();
+        queue_sample.pop();
+        if( ul_refcount )
+            msg_Warn( p_access, "BDAGraph: Non-zero Ref: %d", ul_refcount );
+    }
+    msg_Dbg( p_access, "Queue buffer size = %d", queue_buffer.size() );
+    while( !queue_buffer.empty() )
+    {
+        ul_refcount = queue_buffer.front()->Release();
+        queue_buffer.pop();
+        if( ul_refcount )
+            msg_Warn( p_access, "BDAGraph: Non-zero Ref: %d", ul_refcount );
+    }
+
     if( p_transport_info )
     {
         p_filter_graph->RemoveFilter( p_transport_info );
@@ -1667,6 +1789,11 @@ HRESULT BDAGraph::Destroy()
         p_tuner_device->Release();
         p_tuner_device = NULL;
     }
+    if( p_scanning_tuner )
+    {
+        p_scanning_tuner->Release();
+        p_scanning_tuner = NULL;
+    }
     if( p_network_provider )
     {
         p_filter_graph->RemoveFilter( p_network_provider );
@@ -1674,11 +1801,6 @@ HRESULT BDAGraph::Destroy()
         p_network_provider = NULL;
     }
 
-    if( p_scanning_tuner )
-    {
-        p_scanning_tuner->Release();
-        p_scanning_tuner = NULL;
-    }
     if( p_media_control )
     {
         p_media_control->Release();
@@ -1689,10 +1811,10 @@ HRESULT BDAGraph::Destroy()
         p_filter_graph->Release();
         p_filter_graph = NULL;
     }
-
-    if( d_graph_register )
+    if( p_system_dev_enum )
     {
-        Deregister();
+        p_system_dev_enum->Release();
+        p_system_dev_enum = NULL;
     }
 
     return S_OK;
diff --git a/modules/access/bda/bdagraph.h b/modules/access/bda/bdagraph.h
index 33044e2..42cb1d6 100644
--- a/modules/access/bda/bdagraph.h
+++ b/modules/access/bda/bdagraph.h
@@ -3,7 +3,7 @@
  *****************************************************************************
  * Copyright ( C ) 2007 the VideoLAN team
  *
- * Author: Ken Self <kens at campoz.fslife.co.uk>
+ * Author: Ken Self <kenself(at)optusnet(dot)com(dot)au>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -48,6 +48,7 @@ using namespace std;
 
 #include <dshow.h>
 #include <comcat.h>
+#include <ks.h>
 #include "bdadefs.h"
 #include "bda.h"
 
@@ -67,10 +68,11 @@ public:
 
 private:
     /* ISampleGrabberCB methods */
-    STDMETHODIMP_( ULONG ) AddRef( ) { return 1; }
-    STDMETHODIMP_( ULONG ) Release( ) { return 2; }
+    ULONG ul_cbrc;
+    STDMETHODIMP_( ULONG ) AddRef( ) { return ++ul_cbrc; }
+    STDMETHODIMP_( ULONG ) Release( ) { return --ul_cbrc; }
     STDMETHODIMP QueryInterface( REFIID riid, void** p_p_object )
-        {return E_NOTIMPL;  }
+        { return E_NOTIMPL; }
     STDMETHODIMP SampleCB( double d_time, IMediaSample* p_sample );
     STDMETHODIMP BufferCB( double d_time, BYTE* p_buffer, long l_buffer_len );
 
-- 
1.5.4.3




More information about the vlc-devel mailing list