DVB stream limitation patch (+ stability patches)

Andrew de Quincey <[email protected]>
Newsgroups gmane.comp.video.videolan.vls.devel
Message-ID <[email protected]>
Hi, this patch is against the latest CVS.
It includes my various DVB stability patches.

This one adds the ability to filter which types of stream are taken from
DVB cards. If no configuration is given, the default is to behave
exactly as before; i.e. with no filtering.

Example configuration of a dvb input device:

BEGIN "dvb1"
  DeviceNumber  = "0"
  Dvbrc = "/tmp/dvbrc"
  StreamTypeList = "0x1,0x2,0x3,0x4"
END

This says stream types 1,2,3,4 should be streamed; all other types will
be ignored. If the StreamTypeList item is omitted (or set to ""), all
streams will be accepted.

Merry christmas to everyone!
vls.patch (text/x-patch, 12.8 KB)
diff -Naur vls.ORIGINAL/src/modules/dvbinput/dvbinput.cpp vls/src/modules/dvbinput/dvbinput.cpp
--- vls.ORIGINAL/src/modules/dvbinput/dvbinput.cpp	2002-12-08 15:55:29.000000000 +0000
+++ vls/src/modules/dvbinput/dvbinput.cpp	2002-12-23 23:51:33.000000000 +0000
@@ -114,8 +114,8 @@
                                 m_cCurrentPat(0, 0, true)
 {
   dvb = new DVB;
-  m_iGotPat = 0;   // Did not get the first PAT yet
   m_iGotTpid = 0;  // Did not set the transponder yet
+  demuxUsageCount = 0; // nothing using the demux yet
   m_pConverter = NULL;
   for(int i =0; i < 512; i++)
     m_iDemuxes[i] = -1;
@@ -137,13 +137,49 @@
 {
   int iNumber;
   C_String strType;
+  C_String dvbrc;
+  C_String streamTypeList;
   char filen[FILELEN];
+  int oldPos = 0;
+  int newPos = -1;
 
   // Retrieve config
   C_Application* pApp = C_Application::GetApp();
   ASSERT(pApp);
 
   iNumber = pApp->GetSetting(GetName() + ".DeviceNumber", "0").ToInt();
+  dvbrc = pApp->GetSetting(GetName() + ".Dvbrc", "");
+  if (dvbrc.Length() != 0) {
+    strncpy(filen, dvbrc.GetString(), dvbrc.Length()+1);
+  }
+
+  // parse the stream type list
+  streamTypeList = pApp->GetSetting(GetName() + ".StreamTypeList", "").Strip(" \t");
+  int streamTypeListLength = (int) streamTypeList.Length();
+  if (streamTypeListLength > 0) {
+    while(newPos < streamTypeListLength) {
+
+      // find the next token location
+      newPos = streamTypeList.Find(',', oldPos);
+
+      // if we didn't find it, use the end of the string
+      if (newPos == GEN_ERR) newPos = streamTypeListLength;
+
+      // extract the token
+      C_String curToken = streamTypeList.SubString(oldPos, newPos);
+      
+      // parse it and add to the list
+      int* tmpInt = new int;
+      if (sscanf(curToken.GetString(), "%i", tmpInt) != 1) {
+	throw E_Exception(GEN_ERR, "Invalid entry in StreamTypeList");
+      }
+      m_validStreamTypes.Add(tmpInt);
+      Log(m_hLog, LOG_NOTE, "StreamType " + curToken + " added");
+
+      // update starting search position
+      oldPos = newPos+1;
+    }
+  }
 
   dvb->init("", "", iNumber);
   
@@ -219,10 +255,6 @@
   cConfig.m_pEventHandler = this;
   m_pConverter = pConverterModule->NewMpegConverter(cConfig);
   ASSERT(m_pConverter);
-  
-  // Launch the demux
-  m_pConverter->Create();
-
 }
 
 
@@ -237,16 +269,18 @@
 
   if(m_pConverter)
   {
-    // Stop the input stream
-    try
-    {
-      m_pConverter->Stop();
-    }
-    catch(E_Exception e)
-    {
-      m_cEndInit.Release();
-      delete m_pConverter;
-      throw e;
+    // Stop the input converter if necessary
+    if (m_pConverter->IsRunning()) {
+      try
+	{
+	  m_pConverter->Stop();
+	}
+      catch(E_Exception e)
+	{
+	  m_cEndInit.Release();
+	  delete m_pConverter;
+	  throw e;
+	}
     }
 
     delete m_pConverter;
@@ -455,7 +489,6 @@
 
     // Kludge: signal the first PAT arrival.
     m_cEndInit.Protect();
-    m_iGotPat = 1;
     m_cEndInit.Signal();
     m_cEndInit.Release();
   }
@@ -471,31 +504,46 @@
   int iIndex=m_vProgramNames.Find(pBroadcast->GetProgram()->GetName());
   LogDbg(m_hLog, "DVB Channel found: "+dvb->chans[iIndex].name);
 
-  // Check that if we have already got one broadcast going that this
-  // new one is on the same mux (transponder)
-  if(m_iGotPat && m_iGotTpid != dvb->chans[iIndex].tpid)
-  {
-    LogDbg(m_hLog, "Attempting to start reception from different transponder." \
-           "Existing transponder is " + m_iGotTpid + " asked transponder is " +
-            dvb->chans[iIndex].tpid);
-    return;
-  }
-  
-  if (!m_iGotPat)
-  {
+  // lock the demux usage 
+  demuxUsageM.Lock();
+
+  // If we've not already started the demux, do so, and wait for the first
+  // PAT
+  if (demuxUsageCount == 0) {
     // Set the frontend up
     dvb->SetTP(dvb->chans[iIndex].tpid, dvb->chans[iIndex].satid);
     dvb->set_front();
 
-    // Put a filter on PAT
+    // Launch the demux
+    m_pConverter->Create();
+    
+    // Add a filter for PAT
     SelectPid(&m_cPatDecoder, 0x0000, TS_TYPE_NULL);
-
+    
     // Wait for the first PAT
     m_cEndInit.Wait();
     m_cEndInit.Release();
     m_iGotTpid = dvb->chans[iIndex].tpid; // Remember the transponder
+
+    // update demux counter and unlock
+    demuxUsageCount++;
+    demuxUsageM.UnLock();
+  } else {
+    // Check that if we have already got one broadcast going that this
+    // new one is on the same mux (transponder)
+    if (m_iGotTpid != dvb->chans[iIndex].tpid) {
+      LogDbg(m_hLog, "Attempting to start reception from different " +
+	     "transponder. Exiting transponder is " + m_iGotTpid + 
+	     " new transponder is " + dvb->chans[iIndex].tpid);
+      demuxUsageM.UnLock();
+      return;
+    }
+    
+    // update counter and unlock
+    demuxUsageCount++;
+    demuxUsageM.UnLock();
   }
-  
+
   // Get the program
   dvbpsi_pat_program_t *pProgram =
         m_cCurrentPat.GetProgram(dvb->chans[iIndex].pnr);
@@ -516,19 +564,21 @@
                                                m_pEventHandler, false, false);
 
     C_TsMux *pMux = new C_TsMux(m_pTsProvider, this, pBuffer);
-  
 
     try
     {
+
+      u16 iNumber = pBroadcast->GetProgram()->GetName().ToInt();
+
       pStreamer->Create();
 
       pMux->Attach();
 
-      pMux->AttachProgram(pProgram->i_number, pProgram->i_pid);
+      pMux->AttachProgram(pProgram->i_number, pProgram->i_pid, m_validStreamTypes);
 
-      m_cMuxes.Add(pProgram->i_number, pMux);
+      m_cMuxes.Add(iNumber, pMux);
 
-      m_cStreamers.Add(pProgram->i_number, pStreamer);
+      m_cStreamers.Add(iNumber, pStreamer);
 
     }
     catch(E_Exception e)
@@ -573,8 +623,19 @@
 {
   m_cLock.Lock();
 
-  //Unset the filter on PAT
-  UnselectPid(&m_cPatDecoder, 0x0000);
+  // lock demux counter and decrement usage counter
+  demuxUsageM.Lock();
+  demuxUsageCount--;    
+
+  // if the usage counter is 0, we'll have to remove the PAT filter
+  // and suspend the demux
+  if (demuxUsageCount == 0) {
+    UnselectPid(&m_cPatDecoder, 0x0000);
+    m_pConverter->Stop();
+  }
+  
+  // unlock
+  demuxUsageM.UnLock();
 
   u16 iNumber = pBroadcast->GetProgram()->GetName().ToInt();
 
diff -Naur vls.ORIGINAL/src/modules/dvbinput/dvbinput.h vls/src/modules/dvbinput/dvbinput.h
--- vls.ORIGINAL/src/modules/dvbinput/dvbinput.h	2002-12-08 15:55:29.000000000 +0000
+++ vls/src/modules/dvbinput/dvbinput.h	2002-12-23 23:16:45.000000000 +0000
@@ -87,8 +87,9 @@
   int m_iSendMethod;
   
   // Kludge: signal the first PAT arrival.
-  int m_iGotPat;
-  int m_iGotTpid;
+  int demuxUsageCount;
+  int m_iGotTpid; 
+  C_Mutex demuxUsageM;
   C_Condition m_cEndInit;
 
   // Demuxes' file descriptors
@@ -113,6 +114,9 @@
   // Muxes and streamers
   C_HashTable<u16, C_TsMux> m_cMuxes;
   C_HashTable<u16, C_TsStreamer> m_cStreamers;
+
+  // Valid streams
+  C_Vector<int> m_validStreamTypes;
 };
 
 
diff -Naur vls.ORIGINAL/src/modules/dvbreader/dvbreader.h vls/src/modules/dvbreader/dvbreader.h
--- vls.ORIGINAL/src/modules/dvbreader/dvbreader.h	2002-09-22 02:38:54.000000000 +0100
+++ vls/src/modules/dvbreader/dvbreader.h	2002-12-22 14:29:52.000000000 +0000
@@ -46,6 +46,7 @@
 
   virtual int Read(byte* pBuff, int iSize);
   virtual int Seek(s64 iOffset, int bStartPos);
+  virtual int GetFrame(byte ** pBuff ,int iSize) { return 0;};
   virtual s64 Size();
   virtual s64 GetPos();
 
diff -Naur vls.ORIGINAL/src/mpeg/streamdescr.cpp vls/src/mpeg/streamdescr.cpp
--- vls.ORIGINAL/src/mpeg/streamdescr.cpp	2002-10-07 16:01:22.000000000 +0100
+++ vls/src/mpeg/streamdescr.cpp	2002-12-22 14:16:01.000000000 +0000
@@ -38,6 +38,8 @@
 #   include <stdint.h>
 #endif
 
+#include <stdio.h>
+
 #ifdef HAVE_DVBPSI_DVBPSI_H
 #   include <dvbpsi/dvbpsi.h>
 #   include <dvbpsi/descriptor.h>
diff -Naur vls.ORIGINAL/src/mpeg/tsmux.cpp vls/src/mpeg/tsmux.cpp
--- vls.ORIGINAL/src/mpeg/tsmux.cpp	2002-10-07 16:01:22.000000000 +0100
+++ vls/src/mpeg/tsmux.cpp	2002-12-23 23:54:30.000000000 +0000
@@ -72,11 +72,37 @@
 C_TsMuxPmtDecoder::C_TsMuxPmtDecoder(C_NetList *pTsProvider,
                                      C_TsMux *pMux,
                                      u16 iProgramNumber) :
-                        C_DvbPsiPmtDecoder(iProgramNumber, pTsProvider, this)
+  C_DvbPsiPmtDecoder(iProgramNumber, pTsProvider, this)
 {
   ASSERT(pMux);
 
   m_pMux = pMux;
+  m_streamFilterEnabled = false;
+}
+
+
+//------------------------------------------------------------------------------
+// Constructor
+//------------------------------------------------------------------------------
+C_TsMuxPmtDecoder::C_TsMuxPmtDecoder(C_NetList *pTsProvider, 
+				     C_TsMux *pMux, 
+				     u16 iProgramNumber, 
+				     C_Vector<int>& validStreamTypes) : 
+  C_DvbPsiPmtDecoder(iProgramNumber, pTsProvider, this)
+{
+  ASSERT(pMux);
+  
+  m_pMux = pMux;
+  if (validStreamTypes.Size() > 0) {
+    m_streamFilterEnabled = true;
+    for(unsigned int i=0; i< validStreamTypes.Size(); i++) {
+      int* tmp = new int;
+      *tmp = validStreamTypes[i];
+      m_validStreamTypes.Add(tmp);
+    }
+  } else {
+    m_streamFilterEnabled = false;
+  }
 }
 
 
@@ -104,8 +130,10 @@
     dvbpsi_pmt_es_t* pEs = pLLPmt->p_first_es;
     while(pEs)
     {
-      m_pMux->m_pDemux->UnselectPid(m_pMux, pEs->i_pid);
-      printf("--- %x\n", pEs->i_pid);
+      if (ValidStreamType(pEs->i_type)) {
+	m_pMux->m_pDemux->UnselectPid(m_pMux, pEs->i_pid);
+	printf("--- %x\n", pEs->i_pid);
+      }
       pEs = pEs->p_next;
     }
   }
@@ -139,9 +167,11 @@
       dvbpsi_pmt_es_t* pEs = pLLPmt->p_first_es;
       while(pEs)
       {
-        m_pMux->m_pDemux->UnselectPid(m_pMux, pEs->i_pid);
-        printf("--- %x\n", pEs->i_pid);
-        pEs = pEs->p_next;
+	if (ValidStreamType(pEs->i_type)) {
+	  m_pMux->m_pDemux->UnselectPid(m_pMux, pEs->i_pid);
+	  printf("--- %x\n", pEs->i_pid);
+	}
+	pEs = pEs->p_next;
       }
     }
 
@@ -149,8 +179,10 @@
     dvbpsi_pmt_es_t* pEs = pLLPmt->p_first_es;
     while(pEs)
     {
-      m_pMux->m_pDemux->SelectPid(m_pMux, pEs->i_pid, pEs->i_type);
-      printf("+++ %x\n", pEs->i_pid);
+      if (ValidStreamType(pEs->i_type)) {
+	m_pMux->m_pDemux->SelectPid(m_pMux, pEs->i_pid, pEs->i_type);
+	printf("+++ %x\n", pEs->i_pid);
+      }
       pEs = pEs->p_next;
     }
     m_pMux->m_pDemux->SelectPid(m_pMux, pLLPmt->i_pcr_pid, TS_TYPE_NULL);
@@ -158,6 +190,19 @@
   }
 }
 
+//------------------------------------------------------------------------------
+// Check if videolan should stream a certain type of stream
+//------------------------------------------------------------------------------
+bool C_TsMuxPmtDecoder::ValidStreamType(int iStreamType) {
+  // if the stream type filter is enabled, and if it is not in the valid 
+  // stream type vector, don't include it
+  if (m_streamFilterEnabled && (m_validStreamTypes.Find(iStreamType) == GEN_ERR)) {
+    return false;
+  }
+  
+  // otherwise, it is a valid stream
+  return true;
+}
 
 //******************************************************************************
 // C_TsMux class
@@ -236,7 +281,17 @@
 //------------------------------------------------------------------------------
 // Program selection
 //------------------------------------------------------------------------------
-void C_TsMux::AttachProgram(u16 iProgramNumber, u16 iPmtPid)
+void C_TsMux::AttachProgram(u16 iProgramNumber, u16 iPmtPid) 
+{
+  C_Vector<int> emptyVector;
+  AttachProgram(iProgramNumber, iPmtPid, emptyVector);
+}
+
+
+//------------------------------------------------------------------------------
+// Program selection
+//------------------------------------------------------------------------------
+void C_TsMux::AttachProgram(u16 iProgramNumber, u16 iPmtPid, C_Vector<int>& validStreamTypes)
 {
   // Lock the demux because we're running in another thread
   m_pDemux->Lock();
@@ -244,7 +299,8 @@
   ASSERT(!m_cPmtDecoders.Get(iPmtPid));
 
   C_TsMuxPmtDecoder *pDecoder = new C_TsMuxPmtDecoder(m_pTsProvider, this,
-                                                      iProgramNumber);
+                                                      iProgramNumber, 
+						      validStreamTypes);
   ASSERT(pDecoder);
 
   try
diff -Naur vls.ORIGINAL/src/mpeg/tsmux.h vls/src/mpeg/tsmux.h
--- vls.ORIGINAL/src/mpeg/tsmux.h	2002-04-10 11:17:08.000000000 +0100
+++ vls/src/mpeg/tsmux.h	2002-12-23 23:14:02.000000000 +0000
@@ -54,16 +54,20 @@
 {
 public:
   C_TsMuxPmtDecoder(C_NetList *pTsProvider, C_TsMux *pMux, u16 iProgramNumber);
+  C_TsMuxPmtDecoder(C_NetList *pTsProvider, C_TsMux *pMux, u16 iProgramNumber, C_Vector<int>& validStreamTypes);
   virtual ~C_TsMuxPmtDecoder();
 
   void Detach();
 
 protected:
   virtual void OnDvbPsiPmtEvent(int iEvent);
+  virtual bool ValidStreamType(int iStreamType);
 
 private:
   // Internal data
   C_TsMux *m_pMux;
+  bool m_streamFilterEnabled;
+  C_Vector<int> m_validStreamTypes;
 };
 
 
@@ -82,6 +86,7 @@
   void Detach();
 
   void AttachProgram(u16 iProgramNumber, u16 iPmtPid);
+  void AttachProgram(u16 iProgramNumber, u16 iPmtPid, C_Vector<int>& validStreamTypes);
   void DetachProgram(u16 iPmtPid);
 
   virtual void HandlePacket(C_TsPacket* pPacket);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.