[mythtv] [DVB][PATCH] Fix demux problems + misc. minor stuff

Jesper Sörensen jesper at datapartner.se
Mon Mar 28 14:34:36 UTC 2005


- Make DVB recorder recognize DTS audio streams
- Remove broken dvb_sw_filter option
- Add PCRPID logging
- Remove PS stream id overrides (allows PS recorder to handle multiple 
audio streams)

- Workaround for demux problems caused by the DEC2000-t patch:
Basically, some DVB cards/drivers (e.g. the DEC2000-t) seem to need 
DMX_PES_AUDIO/VIDEO
for the demux, but that causes problems for other cards. The best 
solution is probably to fix the
drivers to handle DMX_PES_OTHER properly, but as a workaround I've added 
an option in
mythtv-setup to activate "hardware decoder" mode for those who need it.

For some background on this, please see Marcus Metzler's e-mail to the 
mythtv-dev list
on 2004-12-04, with the subject: "don't use DMX_PES_VIDEO".

-------------- next part --------------
Index: libs/libmythtv/dbcheck.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/dbcheck.cpp,v
retrieving revision 1.95
diff -u -r1.95 dbcheck.cpp
--- libs/libmythtv/dbcheck.cpp	27 Mar 2005 18:18:56 -0000	1.95
+++ libs/libmythtv/dbcheck.cpp	28 Mar 2005 13:13:35 -0000
@@ -9,7 +9,7 @@
 #include "mythcontext.h"
 #include "mythdbcon.h"
 
-const QString currentDatabaseVersion = "1078";
+const QString currentDatabaseVersion = "1079";
 
 static bool UpdateDBVersionNumber(const QString &newnumber);
 static bool performActualUpdate(const QString updates[], QString version,
@@ -1583,6 +1583,17 @@
             return false;
     }
 
+    if (dbver == "1078")
+    {
+        const QString updates[] = {
+"ALTER TABLE capturecard CHANGE dvb_swfilter dvb_hw_decoder INT DEFAULT '0';",
+"UPDATE capturecard SET dvb_hw_decoder = 0;",
+""
+};
+        if (!performActualUpdate(updates, "1079", dbver))
+            return false;
+    }
+
     return true;
 }
 
Index: libs/libmythtv/dvbrecorder.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/dvbrecorder.cpp,v
retrieving revision 1.48
diff -u -r1.48 dvbrecorder.cpp
--- libs/libmythtv/dvbrecorder.cpp	26 Mar 2005 15:16:49 -0000	1.48
+++ libs/libmythtv/dvbrecorder.cpp	28 Mar 2005 13:13:35 -0000
@@ -70,11 +70,9 @@
     dvbchannel = advbchannel;
 
     _dvb_on_demand_option = false;
-    _software_filter_option = false;
+    _hw_decoder_option = false;
     _record_transport_stream_option = false;
 
-    _software_filter_open = false;
-
     _continuity_error_count = 0;
     _stream_overflow_count = 0;
     _bad_packet_count = 0;
@@ -105,8 +103,8 @@
 {
     if (name == "cardnum")
         _card_number_option = value;
-    else if (name == "swfilter")
-        _software_filter_option = (value == 1);
+    else if (name == "hw_decoder")
+        _hw_decoder_option = (value == 1);
     else if (name == "recordts")
         _record_transport_stream_option = (value == 1);
 #if 0
@@ -223,11 +221,9 @@
         }
     }
     pid_ipack.clear();
-
-    _software_filter_open = false;
 }
 
-void DVBRecorder::OpenFilters(uint16_t pid, ES_Type type)
+void DVBRecorder::OpenFilters(uint16_t pid, ES_Type type, dmx_pes_type_t pes_type)
 {
     VERBOSE(VB_RECORD, QString("DVB#%1 ").arg(_card_number_option) << QString("Adding pid %1").arg(pid));
 
@@ -236,78 +232,32 @@
         WARNING(QString("PID value (%1) is outside DVB specification.")
                         .arg(pid));
 
-    if (!_software_filter_option || !_software_filter_open)
-    {
-        struct dmx_pes_filter_params params;
-        memset(&params, 0, sizeof(params));
-        params.input = DMX_IN_FRONTEND;
-        params.output = DMX_OUT_TS_TAP;
-        params.flags = DMX_IMMEDIATE_START;
-        params.pes_type = DMX_PES_OTHER;
+    struct dmx_pes_filter_params params;
+    memset(&params, 0, sizeof(params));
+    params.input = DMX_IN_FRONTEND;
+    params.output = DMX_OUT_TS_TAP;
+    params.flags = DMX_IMMEDIATE_START;
+    params.pid = pid;
+    params.pes_type = pes_type;
 
-        if ( _software_filter_option )
-        {
-            params.pes_type = DMX_PES_OTHER;
-            params.pid = DMX_DONT_FILTER;
-        }
-        else
-        {
-            params.pid = pid;
-            switch ( type ) 
-            {
-                case ES_TYPE_VIDEO_MPEG1:
-                case ES_TYPE_VIDEO_MPEG2:
-                case ES_TYPE_VIDEO_MPEG4:
-                case ES_TYPE_VIDEO_H264:
-                    params.pes_type = DMX_PES_VIDEO;
-                    break;
-                case ES_TYPE_AUDIO_MPEG1:
-                case ES_TYPE_AUDIO_MPEG2:
-                case ES_TYPE_AUDIO_AAC:
-                case ES_TYPE_AUDIO_AC3:
-                case ES_TYPE_AUDIO_DTS:
-                    params.pes_type = DMX_PES_AUDIO;
-                    break;
-                case ES_TYPE_TELETEXT:
-                    params.pes_type = DMX_PES_TELETEXT;
-                    break;
-                case ES_TYPE_SUBTITLE:
-                    params.pes_type = DMX_PES_SUBTITLE;
-                    break;
-                case ES_TYPE_DATA:
-                    params.pes_type = DMX_PES_PCR;
-                    break;
-                default:
-                    params.pes_type = DMX_PES_OTHER;
-                    break;
-            }
-        }
+    int fd_tmp = open(dvbdevice(DVB_DEV_DEMUX,_card_number_option), O_RDWR);
 
-        int fd_tmp = open(dvbdevice(DVB_DEV_DEMUX,_card_number_option), O_RDWR);
-
-        if (fd_tmp < 0)
-        {
-            ERRNO(QString("Could not open demux device."));
-            return;
-        }
-
-        if (_software_filter_option)
-        {
-            GENERAL("Using Software Filtering.");
-            _software_filter_open = true;
-        }
-
-        if (ioctl(fd_tmp, DMX_SET_PES_FILTER, &params) < 0)
-        {
-            close(fd_tmp);
+    if (fd_tmp < 0)
+    {
+        ERRNO(QString("Could not open demux device."));
+        return;
+    }
 
-            ERRNO(QString("Failed to set demux filter."));
-            return;
-        }
+    if (ioctl(fd_tmp, DMX_SET_PES_FILTER, &params) < 0)
+    {
+        close(fd_tmp);
 
-        _pid_filters.push_back(fd_tmp);
+        ERRNO(QString("Failed to set demux filter."));
+        return;
     }
 
+    _pid_filters.push_back(fd_tmp);
+
     if (_record_transport_stream_option)
     {
         pid_ipack[pid] = NULL;
@@ -381,15 +331,50 @@
     {
         if ((*es).Record)
         {
-            OpenFilters((*es).PID, (*es).Type);
+            int pid = (*es).PID;
+            dmx_pes_type_t pes_type;
+            
+            if (_hw_decoder_option)
+            {
+                switch ((*es).Type)
+                {
+                    case ES_TYPE_AUDIO_MPEG1:
+                    case ES_TYPE_AUDIO_MPEG2:
+                        pes_type = DMX_PES_AUDIO;
+                        break;
+                    case ES_TYPE_VIDEO_MPEG1:
+                    case ES_TYPE_VIDEO_MPEG2:
+                        pes_type = DMX_PES_VIDEO;
+                        break;
+                    case ES_TYPE_TELETEXT:
+                        pes_type = DMX_PES_TELETEXT;
+                        break;
+                    case ES_TYPE_SUBTITLE:
+                        pes_type = DMX_PES_SUBTITLE;
+                        break;
+                    default:
+                        pes_type = DMX_PES_OTHER;
+                        break;
+                }
+            }
+            else
+                pes_type = DMX_PES_OTHER;
+
+            OpenFilters(pid, (*es).Type, pes_type);
 
-            if ((*es).PID == m_pmt.PCRPID)
+            if (_hw_decoder_option)
+            {
+                // Set PCRPID if it's not the same as video
+                if ((pes_type == DMX_PES_VIDEO) && (pid != m_pmt.PCRPID) && (m_pmt.PCRPID != 0))
+                    OpenFilters(m_pmt.PCRPID, ES_TYPE_UNKNOWN, DMX_PES_PCR);
+            }
+            else if (pid == m_pmt.PCRPID)
                 need_pcr_pid = false;
         }
     }
 
-    if (_record_transport_stream_option && need_pcr_pid)
-        OpenFilters(m_pmt.PCRPID, ES_TYPE_UNKNOWN);
+    if (!_hw_decoder_option && need_pcr_pid && (m_pmt.PCRPID != 0))
+        OpenFilters(m_pmt.PCRPID, ES_TYPE_UNKNOWN, DMX_PES_OTHER);
 
 
     if (_pid_filters.size() == 0 && pid_ipack.size() == 0)
@@ -409,6 +394,8 @@
 
     isVideo.clear();
 
+    RECORD(QString("AutoPID for ServiceID=%1, PCRPID=%2").arg(m_pmt.ServiceID).arg(m_pmt.PCRPID));
+
     // Wanted languages:
     QStringList Languages = QStringList::split(",", gContext->GetSetting("PreferredLanguages", ""));
 
@@ -421,7 +408,8 @@
     StreamTypes += ES_TYPE_AUDIO_AC3;
     if (_record_transport_stream_option)
     {
-        // PS recorder can't handle these
+        // The following types are only supported with TS recording
+        StreamTypes += ES_TYPE_AUDIO_DTS;
         StreamTypes += ES_TYPE_AUDIO_AAC;
         StreamTypes += ES_TYPE_TELETEXT;
         StreamTypes += ES_TYPE_SUBTITLE;
@@ -459,10 +447,9 @@
                 continue; // Ignore this stream
         }
 
-        if (!_record_transport_stream_option)
+        if (_hw_decoder_option)
         {
-            // The MPEG PS decoder in Myth currently only handles one stream
-            // of each type, so make sure we don't already have one
+            // Limit hardware decoders to one A/V stream
             switch ((*es).Type)
             {
                 case ES_TYPE_VIDEO_MPEG1:
@@ -477,17 +464,11 @@
                         continue; // Ignore this stream
                     break;
 
-                case ES_TYPE_AUDIO_AC3:
-                    if (flagged.contains(ES_TYPE_AUDIO_AC3))
-                        continue; // Ignore this stream
-                    break;
-
                 default:
                     break;
             }
         }
 
-
         if (Languages.isEmpty() // No specific language wanted
             || (*es).Language.isEmpty() // Component has no language
             || Languages.contains((*es).Language)) // This language is wanted!
@@ -783,7 +764,6 @@
             case PRIVATE_STREAM1:
                 break;
             case AUDIO_STREAM_S ... AUDIO_STREAM_E:
-                buffer[3] = 0xc0; // fix audio ID to 0xC0
                 break;
 
             case VIDEO_STREAM_S ... VIDEO_STREAM_E:
@@ -795,7 +775,6 @@
                 unsigned int state = 0xFFFFFFFF, v = 0;
                 int prvcount = -1;
 
-                buffer[3] = 0xe0; // fix video ID to 0xE0
                 while (bufptr < &buffer[pos] + datalen)
                 {
                     if (++prvcount < 3)
Index: libs/libmythtv/dvbrecorder.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/dvbrecorder.h,v
retrieving revision 1.24
diff -u -r1.24 dvbrecorder.h
--- libs/libmythtv/dvbrecorder.h	31 Jan 2005 05:49:56 -0000	1.24
+++ libs/libmythtv/dvbrecorder.h	28 Mar 2005 13:13:35 -0000
@@ -48,7 +48,7 @@
     void LocalProcessDataTS(unsigned char *buffer, int len);
 
     void CloseFilters();
-    void OpenFilters(uint16_t pid, ES_Type type);
+    void OpenFilters(uint16_t pid, ES_Type type, dmx_pes_type_t pes_type);
     void SetDemuxFilters();
     void AutoPID();
 
@@ -59,7 +59,7 @@
     int  _card_number_option;
     bool _record_transport_stream_option;
     bool _dvb_on_demand_option;
-    bool _software_filter_option;
+    bool _hw_decoder_option;
 
     // DVB stuff
     DVBChannel*     dvbchannel;
@@ -67,7 +67,6 @@
     PMTObject       m_pmt;
     unsigned char   prvpkt[3];
     vector<int>     _pid_filters;
-    bool            _software_filter_open;
     bool            _reset_pid_filters; // set when we want to generate a new filter set
 
     // Stream IDs for the PS recorder
Index: libs/libmythtv/siparser.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/siparser.cpp,v
retrieving revision 1.12
diff -u -r1.12 siparser.cpp
--- libs/libmythtv/siparser.cpp	28 Mar 2005 01:30:25 -0000	1.12
+++ libs/libmythtv/siparser.cpp	28 Mar 2005 13:13:36 -0000
@@ -760,6 +760,14 @@
 
                 switch (descriptor_tag)
                 {
+                    case 0x05: // Registration Descriptor
+                        {
+                            QString format = QString::fromLatin1((const char*) descriptor + 2, 4);
+                            if (format == "DTS1")
+                                e.Type = ES_TYPE_AUDIO_DTS;
+                        }
+                        break;
+
                     case 0x0A: // ISO 639 Language Descriptor
                         e.Language = ParseDescriptorLanguage(descriptor, descriptor_len);
                         break;
Index: libs/libmythtv/tv_rec.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/tv_rec.cpp,v
retrieving revision 1.177
diff -u -r1.177 tv_rec.cpp
--- libs/libmythtv/tv_rec.cpp	28 Mar 2005 08:40:56 -0000	1.177
+++ libs/libmythtv/tv_rec.cpp	28 Mar 2005 13:13:37 -0000
@@ -701,7 +701,7 @@
         nvr->SetOptionsFromProfile(&profile, videodev, audiodev, vbidev, ispip);
 
         nvr->SetOption("dvb_on_demand", dvb_options.dvb_on_demand);
-        nvr->SetOption("swfilter", dvb_options.swfilter);
+        nvr->SetOption("hw_decoder", dvb_options.hw_decoder);
         nvr->SetOption("recordts", dvb_options.recordts);
         nvr->SetOption("wait_for_seqstart", dvb_options.wait_for_seqstart);
         nvr->SetOption("dmx_buf_size", dvb_options.dmx_buf_size);
@@ -1115,7 +1115,7 @@
     MSqlQuery query(MSqlQuery::InitCon());
     query.prepare("SELECT videodevice,vbidevice,audiodevice,"
                   "audioratelimit,defaultinput,cardtype,"
-                  "dvb_swfilter, dvb_recordts,"
+                  "dvb_hw_decoder, dvb_recordts,"
                   "dvb_wait_for_seqstart,dvb_dmx_buf_size,"
                   "dvb_pkt_buf_size, skipbtaudio, dvb_on_demand,"
                   "firewire_port, firewire_node, firewire_speed,"
@@ -1153,7 +1153,7 @@
         if (test != QString::null)
             type = QString::fromUtf8(test);
 
-        dvb_opts.swfilter = query.value(6).toInt();
+        dvb_opts.hw_decoder = query.value(6).toInt();
         dvb_opts.recordts = query.value(7).toInt();
         dvb_opts.wait_for_seqstart = query.value(8).toInt();
         dvb_opts.dmx_buf_size = query.value(9).toInt();
Index: libs/libmythtv/tv_rec.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/tv_rec.h,v
retrieving revision 1.63
diff -u -r1.63 tv_rec.h
--- libs/libmythtv/tv_rec.h	11 Mar 2005 19:18:51 -0000	1.63
+++ libs/libmythtv/tv_rec.h	28 Mar 2005 13:13:37 -0000
@@ -32,7 +32,7 @@
 
 typedef struct _dvb_options_t
 {
-    int swfilter;
+    int hw_decoder;
     int recordts;
     int wait_for_seqstart;
     int dmx_buf_size;
Index: libs/libmythtv/videosource.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/videosource.cpp,v
retrieving revision 1.71
diff -u -r1.71 videosource.cpp
--- libs/libmythtv/videosource.cpp	19 Mar 2005 06:51:41 -0000	1.71
+++ libs/libmythtv/videosource.cpp	28 Mar 2005 13:13:37 -0000
@@ -766,13 +766,14 @@
     };
 };
 
-class DVBSwFilter: public CheckBoxSetting, public CCSetting {
+class DVBHwDecoder: public CheckBoxSetting, public CCSetting {
 public:
-    DVBSwFilter(const CaptureCard& parent):
-        CCSetting(parent, "dvb_swfilter") {
-        setLabel(QObject::tr("Do NOT use DVB driver for filtering."));
-        setHelpText(QObject::tr("(BROKEN) This option is used to get around "
-                    "filtering limitations on some DVB cards."));
+    DVBHwDecoder(const CaptureCard& parent):
+        CCSetting(parent, "dvb_hw_decoder") {
+        setLabel(QObject::tr("Use hardware MPEG decoder"));
+        setHelpText(QObject::tr("If your DVB card has a built in MPEG decoder "
+                    "you can activate it here. "
+                    "(Only for full featured cards & certain USB devices)."));
     };
 };
 
@@ -1982,7 +1983,7 @@
         VerticalConfigurationGroup* rec = new VerticalConfigurationGroup(false);        rec->setLabel(QObject::tr("Recorder Options"));
         rec->setUseLabel(false);
 
-        rec->addChild(new DVBSwFilter(parent));
+        rec->addChild(new DVBHwDecoder(parent));
         rec->addChild(new DVBRecordTS(parent));
         rec->addChild(new DVBNoSeqStart(parent));
         rec->addChild(new DVBOnDemand(parent));


More information about the mythtv-dev mailing list