[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