[mythtv] [patch] hdtv signal check

Daniel Thor Kristjansson danielk at cat.nyu.edu
Fri Feb 20 21:00:09 EST 2004


This patch adds a signal check to TuneTo calls in the Channel class if
you are using HDTV. I've changed the threshold to 65% from the 70% I was
using before after Doug's comment about his 68% channel looking fine.

I have a similar patch for DVBChannel which I'll send in later.

-- Daniel
-------------- next part --------------
Index: libs/libmythtv/channelbase.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/channelbase.h,v
retrieving revision 1.4
diff -u -r1.4 channelbase.h
--- libs/libmythtv/channelbase.h	27 Jan 2004 06:42:33 -0000	1.4
+++ libs/libmythtv/channelbase.h	21 Feb 2004 01:54:53 -0000
@@ -30,6 +30,9 @@
     virtual bool SetChannelByString(const QString &chan) = 0;
     virtual bool ChannelUp(void);
     virtual bool ChannelDown(void);
+    virtual bool CheckSignal(int /*msecWait = 5000*/, 
+			     int /*requiredSignalPercentage = 70*/,
+			     int /*input = 0*/) { return true; }
     virtual bool NextFavorite(void);
 
     virtual int ChangeColour(bool up) { (void)up; return 0; };
Index: libs/libmythtv/channel.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/channel.cpp,v
retrieving revision 1.64
diff -u -r1.64 channel.cpp
--- libs/libmythtv/channel.cpp	5 Feb 2004 22:50:38 -0000	1.64
+++ libs/libmythtv/channel.cpp	21 Feb 2004 01:54:54 -0000
@@ -17,7 +17,7 @@
 #include <iostream>
 using namespace std;
 
-Channel::Channel(TVRec *parent, const QString &videodevice)
+Channel::Channel(TVRec *parent, const QString &videodevice, bool strength)
        : ChannelBase(parent)
 {
     device = videodevice;
@@ -29,6 +29,7 @@
     usingv4l2 = false;
     videomode = VIDEO_MODE_NTSC;
     currentFormat = "";
+    usingstrength = strength;
 }
 
 Channel::~Channel(void)
@@ -46,7 +47,7 @@
         isopen = true;
     else
     {
-         cerr << "Channel::Open(): Can't open: " << device << endl;
+         VERBOSE(VB_IMPORTANT, QString("Channel::Open(): Can't open: %1").arg(device));
          perror(device.ascii());
          return false;
     }
@@ -281,8 +282,8 @@
 
         if (chancount > totalChannels)
         {
-            cerr << "Error, couldn't find any available channels.\n";
-            cerr << "Your database is most likely setup incorrectly.\n";
+	    VERBOSE(VB_IMPORTANT, "Error, couldn't find any available channels.");
+            VERBOSE(VB_IMPORTANT, "Your database is most likely setup incorrectly.");
             break;
         }
     }
@@ -314,8 +315,8 @@
 
         if (chancount > totalChannels)
         {
-            cerr << "Error, couldn't find any available channels.\n";
-            cerr << "Your database is most likely setup incorrectly.\n";
+	    VERBOSE(VB_IMPORTANT, "Error, couldn't find any available channels.");
+            VERBOSE(VB_IMPORTANT, "Your database is most likely setup incorrectly.");
             break;
         }
     }
@@ -327,7 +328,7 @@
 {
     if (!Open())
     {
-        cerr << "channel object wasn't open, can't change channels\n";
+	VERBOSE(VB_IMPORTANT, "Channel object wasn't open, can't change channels");
         return false;
     }
 
@@ -401,6 +402,38 @@
     return true;
 }
 
+template<typename V>
+V clamp(V val, V minv, V maxv) { return std::min(maxv, std::max(minv, val)); }
+
+// Returns ATSC signal strength 0-100. >75 is good.
+int signalStrengthATSC(int device, int input) {
+    struct video_signal vsig;
+    int ioctlval = ioctl(device,VIDIOCGSIGNAL,&vsig);
+    if (-1==ioctlval) {
+	perror("VIDIOCGSIGNAL problem in channel.h's signalStrengthATSC()");
+	return 0;
+    }
+    int signal = (input==0) ? vsig.strength : vsig.aux;
+    if ((signal&0xff)!=0x43) return 0;
+    else return clamp(101-(signal>>9), 0, 100);
+}
+
+bool Channel::CheckSignal(int msecTotal, int reqSignal, int input) {
+    int msecSleep=100, maxSignal=0, i=0;
+    msecTotal=max(msecSleep, msecTotal);
+    if (usingstrength) {
+	for (i=0; i<(msecTotal/msecSleep)+1; i++) {
+	    if (0!=i) usleep(msecSleep);
+	    maxSignal=max(maxSignal, signalStrengthATSC(videofd, input));
+	    if (maxSignal>=reqSignal) break;
+	}
+	VERBOSE(VB_IMPORTANT, QString("Maximum signal strength detected: %1\% after %2 msec wait").
+		arg(maxSignal).arg(i*msecSleep));
+	if (maxSignal<reqSignal) return false;
+    }
+    return true;
+}
+
 bool Channel::TuneTo(const QString &channum, int finetune)
 {
     int i = GetCurrentChannelNum(channum);
@@ -408,6 +441,8 @@
         return false;
 
     int frequency = curList[i].freq * 16 / 1000 + finetune;
+    VERBOSE(VB_CHANNEL, QString("TuneTo(%1) curList[i].freq(%2) freq*16(%3)")
+	    .arg(channum).arg(curList[i].freq).arg(frequency));
 
     if (usingv4l2)
     {
@@ -421,7 +456,7 @@
             perror("VIDIOC_S_FREQUENCY");
             return false;
         }
-        return true;
+        return CheckSignal();
     }
 
     if (ioctl(videofd, VIDIOCSFREQ, &frequency) == -1)
@@ -430,7 +465,7 @@
         return false;
     }
 
-    return true;
+    return CheckSignal();
 }
 
 void Channel::SwitchToInput(int newcapchannel, bool setstarting)
Index: libs/libmythtv/channel.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/channel.h,v
retrieving revision 1.27
diff -u -r1.27 channel.h
--- libs/libmythtv/channel.h	5 Feb 2004 22:50:38 -0000	1.27
+++ libs/libmythtv/channel.h	21 Feb 2004 01:54:55 -0000
@@ -14,7 +14,7 @@
 class Channel : public ChannelBase
 {
  public:
-    Channel(TVRec *parent, const QString &videodevice);
+    Channel(TVRec *parent, const QString &videodevice, bool strength=false);
     virtual ~Channel(void);
 
     bool Open(void);
@@ -26,6 +26,9 @@
     bool SetChannelByString(const QString &chan); 
     bool ChannelUp(void);
     bool ChannelDown(void);
+    bool CheckSignal(int msecWait = 5000, 
+		     int requiredSignalPercentage = 65,
+		     int input = 0);
 
     unsigned short *Channel::GetV4L1Field(int attrib, 
                                           struct video_picture &vid_pic);
@@ -62,6 +65,7 @@
 
     int videomode;
     bool usingv4l2;
+    bool usingstrength;
 
     QString currentFormat;
 
Index: libs/libmythtv/tv_rec.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/tv_rec.cpp,v
retrieving revision 1.139
diff -u -r1.139 tv_rec.cpp
--- libs/libmythtv/tv_rec.cpp	19 Feb 2004 08:26:04 -0000	1.139
+++ libs/libmythtv/tv_rec.cpp	21 Feb 2004 01:54:56 -0000
@@ -94,7 +94,7 @@
     }
     else // "V4L" or "MPEG", ie, analog TV, or "HDTV"
     {
-        Channel *achannel = new Channel(this, videodev);
+        Channel *achannel = new Channel(this, videodev, (cardtype == "HDTV"));
         channel = achannel; // here for SetFormat()->RetrieveInputChannels()
         channel->Open();
         achannel->SetFormat(gContext->GetSetting("TVFormat"));
@@ -486,26 +486,48 @@
         autoTranscode = profile.byName("autotranscode")->getValue().toInt();
 
         SetupRecorder(profile);
-        nvr->SetRecording(curRecording);
-        nvr->SetDB(db_conn, &db_lock);
-        if (channel != NULL)
-            nvr->ChannelNameChanged(channel->GetCurrentName());
-
-        SetVideoFiltersForChannel(channel, channel->GetCurrentName());
-        if (channel->Open())
-        {
-            channel->SetBrightness();
-            channel->SetContrast();
-            channel->SetColour();
-            channel->SetHue();
-            channel->Close();
-        }
-
-        pthread_create(&encode, NULL, SpawnEncode, nvr);
-
-        while (!nvr->IsRecording() && !nvr->IsErrored())
-            usleep(50);
 
+	bool error=false;
+	if (channel != NULL)
+        { 
+	    // If there is a tuner make sure this is a valid station
+	    // hdtv will block for a long time if we try to get
+	    // mpeg ts packets from outer space.
+	    bool success=channel->Open();
+	    if (success)
+            {
+		success=channel->SetChannelByString(channel->GetCurrentName());
+		if (!success)
+		{
+		    VERBOSE(VB_IMPORTANT, "Signal level too low?");
+		    error = true;
+		}
+		channel->Close();
+	    } else 
+		error = true;
+	}
+	if (!error) 
+        {
+	    nvr->SetRecording(curRecording);
+	    nvr->SetDB(db_conn, &db_lock);
+	    if (channel != NULL)
+		nvr->ChannelNameChanged(channel->GetCurrentName());
+	    
+	    SetVideoFiltersForChannel(channel, channel->GetCurrentName());
+            if (channel->Open())
+            {
+                channel->SetBrightness();
+                channel->SetContrast();
+                channel->SetColour();
+                channel->SetHue();
+                channel->Close();
+            }
+	    pthread_create(&encode, NULL, SpawnEncode, nvr);
+	    
+	    while (!nvr->IsRecording() && !nvr->IsErrored())
+		usleep(50);
+	} else 
+	    VERBOSE(VB_IMPORTANT, "Tuning Error -- aborting recording");
         if (nvr->IsRecording())
         {
             // evil.


More information about the mythtv-dev mailing list