[mythtv] hdtv signal strength patch v9 (v4l2 support)

Daniel Thor Kristjansson danielk at cat.nyu.edu
Tue May 18 12:51:51 EDT 2004


Consider this experimental. It uses the v4l2 support added by the new
pcHDTV drivers for linux 2.6.6 to detect the signal strength. This is
not enough to get MythTV working with the new drivers, but it's a step
in the right direction.

-- Daniel
-------------- next part --------------
Index: libs/libmythtv/channel.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/channel.cpp,v
retrieving revision 1.67
diff -u -r1.67 channel.cpp
--- libs/libmythtv/channel.cpp	19 Apr 2004 10:35:37 -0000	1.67
+++ libs/libmythtv/channel.cpp	18 May 2004 16:47:31 -0000
@@ -47,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;
     }
@@ -282,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;
         }
     }
@@ -315,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;
         }
     }
@@ -330,7 +330,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;
     }
 
@@ -395,6 +395,8 @@
     int frequency = freqid.toInt(&ok);
     bool isFrequency = ok && frequency > 50000;
 
+    SetFormat(tvformat);
+
     // Tune
     if (externalChanger[currentcapchannel].isEmpty())
     {
@@ -415,8 +417,6 @@
 
     curchannelname = chan;
 
-    SetFormat(tvformat);
-
     pParent->SetVideoFiltersForChannel(this, chan);
     SetContrast();
     SetColour();
@@ -451,19 +451,44 @@
         return clamp(101 - (signal >> 9), 0, 100);
 }
 
+// Returns ATSC signal strength 0-100. >75 is good. Using v4l2.
+int signalStrengthATSC_v4l2(int device, int input) 
+{
+    struct v4l2_tuner vsig;
+    vsig.index = input;
+
+    int ioctlval = ioctl(device,VIDIOC_G_TUNER, &vsig);
+    if (ioctlval == -1) 
+    {
+        perror("VIDIOC_G_TUNER problem in channel.h's signalStrengthATSC()");
+        return 0;
+    }
+    VERBOSE(VB_CHANNEL, QString("signal strength: %1").arg(vsig.signal));
+
+    return clamp(vsig.signal, 0, 100);
+}
+
 bool Channel::CheckSignal(int msecTotal, int reqSignal, int input) 
 {
-    int msecSleep = 100, maxSignal = 0, i = 0;
+    int msecSleep = 500, maxSignal = 0, i = 0;
 
     msecTotal = max(msecSleep, msecTotal);
 
     if (usingstrength) 
     {
+        VERBOSE(VB_CHANNEL, QString("CheckSignal(%1, %2, %3) usingv4l2(%4)")
+                .arg(msecTotal).arg(reqSignal).arg(input).arg(usingv4l2));
+
         for (i = 0; i < (msecTotal / msecSleep) + 1; i++) 
         {
             if (i != 0) 
                 usleep(msecSleep);
-            maxSignal = max(maxSignal, signalStrengthATSC(videofd, input));
+
+            if (usingv4l2)
+                maxSignal = max(maxSignal, signalStrengthATSC_v4l2(videofd, input));
+            else
+                maxSignal = max(maxSignal, signalStrengthATSC(videofd, input));
+
             if (maxSignal >= reqSignal) 
                 break;
         }
@@ -485,6 +510,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));
 
     VERBOSE(VB_CHANNEL, QString("TuneTo(%1) curList[i].freq(%2)")
                                 .arg(channum).arg(curList[i].freq));
@@ -496,6 +523,13 @@
 {
     VERBOSE(VB_CHANNEL, QString("TuneToFrequency(%1)").arg(frequency));
 
+    int signalThresholdWait = 5000;
+    int signalThreshold = 65;
+    if (usingstrength) {
+        gContext->GetNumSetting("ATSCCheckSignalWait", 5000);
+        gContext->GetNumSetting("ATSCCheckSignalThreshold", 65);
+    }
+
     if (usingv4l2)
     {
         struct v4l2_frequency vf;
@@ -508,7 +542,7 @@
             perror("VIDIOC_S_FREQUENCY");
             return false;
         }
-        return CheckSignal();
+        return CheckSignal(signalThresholdWait, signalThreshold, currentcapchannel);
     }
 
     if (ioctl(videofd, VIDIOCSFREQ, &frequency) == -1)
@@ -517,7 +551,7 @@
         return false;
     }
 
-    return CheckSignal();
+    return CheckSignal(signalThresholdWait, signalThreshold, currentcapchannel);
 }
 
 void Channel::SwitchToInput(int newcapchannel, bool setstarting)
Index: libs/libmythtv/tv_rec.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/tv_rec.cpp,v
retrieving revision 1.147
diff -u -r1.147 tv_rec.cpp
--- libs/libmythtv/tv_rec.cpp	15 May 2004 15:01:10 -0000	1.147
+++ libs/libmythtv/tv_rec.cpp	18 May 2004 16:47:32 -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,47 @@
         autoTranscode = profile.byName("autotranscode")->getValue().toInt();
 
         SetupRecorder(profile);
-        nvr->SetRecording(curRecording);
-        nvr->SetDB(db_conn, &db_lock);
+        bool error=false;
         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);
-
+        { 
+            // 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.
Index: programs/mythfrontend/globalsettings.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/programs/mythfrontend/globalsettings.cpp,v
retrieving revision 1.162
diff -u -r1.162 globalsettings.cpp
--- programs/mythfrontend/globalsettings.cpp	8 May 2004 00:46:15 -0000	1.162
+++ programs/mythfrontend/globalsettings.cpp	18 May 2004 16:47:34 -0000
@@ -1339,6 +1339,35 @@
     };
 };
 
+class ATSCCheckSignalWait: public SpinBoxSetting, public BackendSetting {
+public:
+    ATSCCheckSignalWait():
+        SpinBoxSetting(1000, 10000, 250),
+        BackendSetting("ATSCCheckSignalWait") {
+        setLabel(QObject::tr("Wait for ATSC signal lock (msec)"));
+        setHelpText(QObject::tr("MythTV can check the signal strength "
+                      "When you tune into a HDTV or other over-the-air "
+                      "digital station. This value is the number of "
+                      "milliseconds to allow before we give up trying to "
+                      "get an acceptible signal."));
+        setValue(5000);
+    };
+};
+
+class ATSCCheckSignalThreshold: public SliderSetting, public GlobalSetting {
+public:
+    ATSCCheckSignalThreshold():
+        SliderSetting(50, 90, 1),
+        GlobalSetting("ATSCCheckSignalThreshold") {
+        setLabel(QObject::tr("ATSC Signal Threshold"));
+        setHelpText(QObject::tr("Threshold for a signal to be considered "
+                      "acceptible. If you set this too low Myth may crash, "
+                      "if you set it too low you may not be able to tune "
+                      "to channels on which reception is good."));
+        setValue(65);
+    };
+};
+
 class SmartChannelChange: public CheckBoxSetting, public GlobalSetting {
 public:
     SmartChannelChange():
@@ -2288,6 +2317,8 @@
     general->addChild(new AdvancedRecord());
     general->addChild(new ChannelFormat());
     general->addChild(new LongChannelFormat());
+    general->addChild(new ATSCCheckSignalWait());
+    general->addChild(new ATSCCheckSignalThreshold());
     addChild(general);
 
     VerticalConfigurationGroup* autoexp = new VerticalConfigurationGroup(false);


More information about the mythtv-dev mailing list