[mythtv] [patch] DVB auto-pid determination

Base Commander base_commander at hotmail.com
Sat Feb 7 15:38:38 EST 2004


The following patch allows MythTV to automagically determine the correct 
PIDs for a channel once tuned to the correct transponder by parsing the PMT. 
  If the cached database entries for the channel are different from what 
gets picked up from the PMT, we update the database and re-tune the channel.

Using this patch, you should be able to "delete * from dvb_pid" and have 
MythTV autopopulate the correct entries for each channel as you tune to it.

This change also ensures that the PMT change event will always get hooked up 
to the DVBCam object, even if no CAM is present, keeping the PMT cache up to 
date for all channels on all systems.

Index: dvbchannel.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/dvbchannel.cpp,v
retrieving revision 1.16
diff -u -r1.16 dvbchannel.cpp
--- dvbchannel.cpp	23 Jan 2004 06:01:15 -0000	1.16
+++ dvbchannel.cpp	7 Feb 2004 20:22:20 -0000
@@ -128,13 +128,81 @@
     {
         connect(this, SIGNAL(ChannelChanged(dvb_channel_t&)),
                 dvbcam, SLOT(ChannelChanged(dvb_channel_t&)));
-        connect(dvbsct, SIGNAL(ChannelChanged(dvb_channel_t&, uint8_t*, 
int)),
-                dvbcam, SLOT(ChannelChanged(dvb_channel_t&, uint8_t*, 
int)));
     }

+    connect(dvbsct, SIGNAL(ChannelChanged(dvb_channel_t&, uint8_t*, int)),
+            dvbcam, SLOT(ChannelChanged(dvb_channel_t&, uint8_t*, int)));
+    connect(dvbsct, SIGNAL(ChannelUpdated(dvb_channel_t&)),
+            this, SLOT(ChannelUpdated(dvb_channel_t&)));
+
     return isOpen = true;
}

+void DVBChannel::ChannelUpdated(dvb_channel_t& chan)
+{
+    QSqlDatabase    *db_conn;
+    pthread_mutex_t db_lock;
+
+    pParent->CheckChannel((ChannelBase*)this, 0,
+                               db_conn, db_lock);
+
+    pthread_mutex_lock(&db_lock);
+
+    MythContext::KickDatabase(db_conn);
+
+    // TODO: select by service/network/transport
+    QString thequery = QString("SELECT chanid FROM dvb_channel WHERE 
serviceID='%1'")
+                       .arg(chan.serviceID);
+    QSqlQuery query = db_conn->exec(thequery);
+
+    if (!query.isActive())
+        MythContext::DBError("GetChannelOptions - ChanID", query);
+
+    if (query.numRowsAffected() <= 0)
+    {
+        ERROR("Unable to find channel in database.");
+        pthread_mutex_unlock(&db_lock);
+        return;
+    }
+
+    query.next();
+    int chanid = query.value(0).toInt();
+
+    CHANNEL(QString("Channel options updated for channel 
#%1.").arg(chanid));
+
+    thequery = QString("DELETE FROM dvb_pids WHERE chanid=%1 AND (type='v' 
OR type='a')")
+                               .arg(chanid);
+    query = db_conn->exec(thequery);
+
+    if (!query.isActive())
+        MythContext::DBError("ChannelUpdated", query);
+
+    for (dvb_pid_t::iterator it = chan.pids.video.begin(); it != 
chan.pids.video.end(); it++)
+    {
+        QString thequery = QString("INSERT INTO dvb_pids(chanid, type, pid) 
values (%1,'%2',%3)")
+                                   .arg(chanid).arg('v').arg(*it);
+        QSqlQuery query = db_conn->exec(thequery);
+
+        if (!query.isActive())
+            MythContext::DBError("ChannelUpdated", query);
+    }
+
+    for (dvb_pid_t::iterator it = chan.pids.audio.begin(); it != 
chan.pids.audio.end(); it++)
+    {
+        QString thequery = QString("INSERT INTO dvb_pids(chanid, type, pid) 
values (%1,'%2',%3) ")
+                                   .arg(chanid).arg('a').arg(*it);
+        QSqlQuery query = db_conn->exec(thequery);
+
+        if (!query.isActive())
+            MythContext::DBError("ChannelUpdated", query);
+    }
+
+    pthread_mutex_unlock(&db_lock);
+
+    chan_opts = chan;
+    ChannelChanged(chan_opts);
+}
+
bool DVBChannel::SetChannelByString(const QString &chan)
{
     if (curchannelname == chan)
@@ -289,8 +357,10 @@
     if (!ParseQuery(query))
         return false;

+    // This isn't a fatal error - we can still tune to the channel for 
other reasons
     if (!GetChannelPids(db_conn, db_lock, chanid))
-        return false;
+        WARNING(QString("Couldn't retrieve PIDs for channel %1.")
+            .arg(channum));

     return true;
}
Index: dvbchannel.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/dvbchannel.h,v
retrieving revision 1.11
diff -u -r1.11 dvbchannel.h
--- dvbchannel.h	23 Jan 2004 06:01:16 -0000	1.11
+++ dvbchannel.h	7 Feb 2004 20:22:20 -0000
@@ -67,6 +67,9 @@
     void RecorderStarted();
     bool FillFrontendStats(dvb_stats_t &stats);

+public slots:
+    void ChannelUpdated(dvb_channel_t& chan);
+
signals:
     void ChannelChanged(dvb_channel_t& chan);

Index: dvbsections.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/dvbsections.cpp,v
retrieving revision 1.3
diff -u -r1.3 dvbsections.cpp
--- dvbsections.cpp	22 Jan 2004 03:56:14 -0000	1.3
+++ dvbsections.cpp	7 Feb 2004 20:22:20 -0000
@@ -31,6 +31,8 @@
#include <map>
#include <cstdlib>
#include <cstdio>
+#include <set>
+#include <algorithm>
using namespace std;

#include <fcntl.h>
@@ -317,7 +319,66 @@
         curpmtsize = size - 4;
         pthread_mutex_unlock(&pmap_lock);

+        dvbpids pids;
+        uint16_t program_info_length;
+        uint16_t stream_type;
+        uint16_t elementary_pid;
+        uint16_t es_info_length;
+
+        program_info_length = (buffer[2]&0xf)<<8 | buffer[3];
+        buffer += program_info_length + 4;
+        size -= program_info_length + 4;
+
+        set<uint16_t> apids_old, apids_new;
+        set<uint16_t> vpids_old, vpids_new;
+
+        for (dvb_pid_t::iterator it = chan_opts.pids.audio.begin(); it != 
chan_opts.pids.audio.end(); it++)
+            apids_old.insert(*it);
+        for (dvb_pid_t::iterator it = chan_opts.pids.video.begin(); it != 
chan_opts.pids.video.end(); it++)
+            vpids_old.insert(*it);
+
+        while (size > 4)
+        {
+            stream_type = buffer[0];
+            elementary_pid = (buffer[1]&0x1f)<<8 | buffer[2];
+            es_info_length = (buffer[3]&0xf)<<8 | buffer[4];
+
+            // ISO video stream
+            if (stream_type == 2)
+            {
+                vpids_new.insert( elementary_pid );
+                pids.video.push_back(elementary_pid);
+            }
+
+            // ISO audio stream
+            if (stream_type == 4)
+            {
+                apids_new.insert( elementary_pid );
+                pids.audio.push_back(elementary_pid);
+            }
+
+            // TODO: add other streams?
+
+            buffer += es_info_length + 5;
+            size -= es_info_length + 5;
+        }
+
+        vector<uint16_t> difference;
+        set_symmetric_difference(apids_old.begin(), apids_old.end(), 
apids_new.begin(), apids_new.end(),
+            inserter(difference, difference.begin()));
+        set_symmetric_difference(vpids_old.begin(), vpids_old.end(), 
vpids_new.begin(), vpids_new.end(),
+            inserter(difference, difference.begin()));
+
+        // If we found PIDs for the channel from the PMT and they're 
different from the old
+        // ones, fire the event to update the database.
+        if ((apids_new.size() > 0 || vpids_new.size() > 0) && 
difference.size() > 0)
+        {
+            chan_opts.pids.video = pids.video;
+            chan_opts.pids.audio = pids.audio;
+
+            ChannelUpdated(chan_opts);
+        }
+
         ChannelChanged(chan_opts, curpmtbuf, curpmtsize);
     }
}
-
Index: dvbsections.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/dvbsections.h,v
retrieving revision 1.2
diff -u -r1.2 dvbsections.h
--- dvbsections.h	22 Jan 2004 03:56:14 -0000	1.2
+++ dvbsections.h	7 Feb 2004 20:22:20 -0000
@@ -79,6 +79,7 @@
     void ChannelChanged(dvb_channel_t& chan);

signals:
+    void ChannelUpdated(dvb_channel_t& chan);
     void ChannelChanged(dvb_channel_t& chan, uint8_t* pmt, int len);

private:

_________________________________________________________________
Tired of spam? Get advanced junk mail protection with MSN 8. 
http://join.msn.com/?page=features/junkmail



More information about the mythtv-dev mailing list