New Recorder Support

What would you like to see in MythTV and why? Find others who might want to help implement your ideas!
Forum rules
Please be reasonable and positive with your feature requests, remember that all contributions to MythTV are by volunteers in their spare time. MythTV won't support piracy in any form, including torrents and use of soft cams, so to avoid embarrassment please do not ask.

* One suggestion per thread please. Do not post new suggestions in replies. *
Post Reply
rdudleyc
Newcomer
Posts: 13
Joined: Mon Mar 09, 2015 10:32 am
United States of America

New Recorder Support

Post by rdudleyc »

I recently purchased a Chinese HDMI Encoder (http://www.oupree.com/OPR-NH100-1-Chann ... coder.html). it's a bit of a hybrid of an HDPVR and a HDHomerun devices

I've managed to hack in some capability leveraging the dummy IPTV m3u entries and event scripts -- it's not pretty but shows that things can be made to work - sort of. Unfortunately, I'm not really a programmer, so doing a real integration efforts is beyond my skill base.

I'd love to see support in MythTv for this devices or it's many clones.
rdudleyc
Newcomer
Posts: 13
Joined: Mon Mar 09, 2015 10:32 am
United States of America

Re: New Recorder Support

Post by rdudleyc »

I decided to take this one on myself.

Using the current 0.28 preview, I built a working system using the IP/TV support, some of the standard event scripting features, and one of the APIs.

The how-to write-up is now posted in the wiki

https://www.mythtv.org/wiki/IPTV_Encode ... ure_Device
User avatar
pvr4me
Senior
Posts: 763
Joined: Fri Feb 07, 2014 7:25 pm
Location: near Toronto, Canada
Contact:
Canada

Re: New Recorder Support

Post by pvr4me »

Great contribution!

If you don't mind, how much did the encoder box cost you?

Craig
Formerly the MacPorts guy.
rdudleyc
Newcomer
Posts: 13
Joined: Mon Mar 09, 2015 10:32 am
United States of America

Re: New Recorder Support

Post by rdudleyc »

approx $200 US.
feathers
Newcomer
Posts: 4
Joined: Fri Nov 20, 2015 3:47 am
Australia

Re: New Recorder Support

Post by feathers »

What would happen if you set the 60fps trick on both streams ?
rdudleyc
Newcomer
Posts: 13
Joined: Mon Mar 09, 2015 10:32 am
United States of America

Re: New Recorder Support

Post by rdudleyc »

The chip specs says is won't work.
I suspect that strange things will happen due to insufficient bandwidth in key components but I don't honestly know.
feathers
Newcomer
Posts: 4
Joined: Fri Nov 20, 2015 3:47 am
Australia

Re: New Recorder Support

Post by feathers »

Is there any chance you could test if 50fps works (on one stream only) ? I assume it would but would be nice to know before I take the plunge. If you could share the name of the chipset too that would be great.
rdudleyc
Newcomer
Posts: 13
Joined: Mon Mar 09, 2015 10:32 am
United States of America

Re: New Recorder Support

Post by rdudleyc »

The main chip in mine is the HiSilicon HI3516A. some use the older Hi3516. There are of course numerous other chips for things like the HDMI interface, Ethernet, etc. Here's the sales spec sheet for the HiSilicon chip -- http://www.ipcameramodule.com/wp-conten ... -Sheet.pdf

As for a 50fps test, I'm sorry, but I don't have access to a 50fps source. Someplace I have a copy of the engineering spec for the Hi3516A. That document does list the common 50FPS rates as supported.
feathers
Newcomer
Posts: 4
Joined: Fri Nov 20, 2015 3:47 am
Australia

Re: New Recorder Support

Post by feathers »

Thanks, I ordered one, will post results when it arrives.
feathers
Newcomer
Posts: 4
Joined: Fri Nov 20, 2015 3:47 am
Australia

Re: New Recorder Support

Post by feathers »

I received my device :)

It is the dtvane DMB-8800A variant.

Setting the 50fps trick @ 1080p causes the device to crash after a few seconds of streaming. Had to change the settings via the web interface back to 25fps then physically power cycle the encoder to recover it.

Setting the 50fps trick @ 720p works great. (Note that it's not necessary to adjust the input resolution, it accepts the 1080p50 signal perfectly, just the output must be 720p50).

Thanks rdudley for all your help. :D
harpax
Newcomer
Posts: 12
Joined: Mon Feb 10, 2014 11:47 pm
Canada

Re: New Recorder Support

Post by harpax »

First off I want to say thanks to the OP for the great wiki article and the idea of using these things in general. Component outputs on STBs are becoming increasingly rare and these encoders provide an option for those of us in Canada who really have no option but using the STB's provided to us by the telecoms.

I purchased one of these encoders, a unisheen BM3000-HDMI. This seems to be a "2nd generation" version of the encoders you have on the wiki (I think the equivalent to the one the OP bought is http://www.oupree.com/New-H.264-1-Chann ... coder.html) . It can handle more streams and 1080p@60fps without any extra work (this is available in the GUI).

I've done some work integrating this device into MythTV and I have developed a basic patch to add external channel changing capability to the IPTV recorder. Note that I did not patch the GUI, you will need set the appropriate location in the database to point to your script. I have also incorporated a few patches for existing known issues on the MythTV TRAC that I ran into. I don't have access to the wiki (I requested it in a separate thread) so if someone with access finds this information useful please feel free to add it to the wiki article.

IPTV External Channel Change
The external channel change patch involves patching 3 files:

This patch pulls the IPTV tuning block out of the conditional which prevented it from running unless no external channel change script was present in the database. In this case we need to tune "twice". Once for the external channel change script, and again if IPTV is in use to "tune" to the URL.

Code: Select all

--- libs/libmythtv/recorders/dtvchannel.cpp.orig        2017-01-14 20:10:11.426837194 -0500
+++ libs/libmythtv/recorders/dtvchannel.cpp     2017-01-14 20:28:47.141421855 -0500
@@ -266,20 +266,9 @@
     bool ok = true;
     if (m_externalChanger.isEmpty())
     {
-        if (IsIPTV())
-        {
-            int chanid = ChannelUtil::GetChanID(m_sourceid, channum);
-            IPTVTuningData tuning = ChannelUtil::GetIPTVTuningData(chanid);
-            if (!Tune(tuning, false))
-            {
-                LOG(VB_GENERAL, LOG_ERR, loc + "Tuning to IPTV URL");
-                ClearDTVInfo();
-                ok = false;
-            }
-        }
-        else if (m_name.contains("composite", Qt::CaseInsensitive) ||
-                 m_name.contains("component", Qt::CaseInsensitive) ||
-                 m_name.contains("s-video", Qt::CaseInsensitive))
+        if (m_name.contains("composite", Qt::CaseInsensitive) ||
+            m_name.contains("component", Qt::CaseInsensitive) ||
+            m_name.contains("s-video", Qt::CaseInsensitive))
         {
             LOG(VB_GENERAL, LOG_WARNING, loc + "You have not set "
                     "an external channel changing"
@@ -322,6 +311,18 @@
         }
     }

+    if (IsIPTV())
+    {
+        int chanid = ChannelUtil::GetChanID(m_sourceid, channum);
+        IPTVTuningData tuning = ChannelUtil::GetIPTVTuningData(chanid);
+        if (!Tune(tuning, false))
+        {
+            LOG(VB_GENERAL, LOG_ERR, loc + "Tuning to IPTV URL");
+            ClearDTVInfo();
+            ok = false;
+        }
+    }
+
     LOG(VB_CHANNEL, LOG_INFO, loc + ((ok) ? "success" : "failure"));

     if (!ok)
This patch causes the IPTV channel scanner to set the freq_id for IPTV channels in the database to match the channel number. This is needed because the freq_id is the parameter passed to the external channel change script when it runs so it knows what channel to change to. This field was previously set to NULL, so I don't think it was used by the recorder.

Code: Select all

--- libs/libmythtv/channelscan/iptvchannelfetcher.cpp.orig      2017-01-14 20:10:03.866888041 -0500
+++ libs/libmythtv/channelscan/iptvchannelfetcher.cpp   2017-01-14 20:17:41.395855762 -0500
@@ -173,9 +173,10 @@
                                                        tr("Adding %1").arg(msg));
                 }
                 chanid = ChannelUtil::CreateChanID(_sourceid, channum);
+                QString freq_id = channum;
                 ChannelUtil::CreateChannel(0, _sourceid, chanid, name, name,
                                            channum, programnumber, 0, 0,
-                                           false, false, false, QString::null,
+                                           false, false, false, freq_id,
                                            QString::null, "Default", xmltvid);
                 ChannelUtil::CreateIPTVTuningData(chanid, (*it).m_tuning);
             }
@@ -186,9 +187,10 @@
                     _scan_monitor->ScanAppendTextToLog(
                                                tr("Updating %1").arg(msg));
                 }
+                QString freq_id = channum;
                 ChannelUtil::UpdateChannel(0, _sourceid, chanid, name, name,
                                            channum, programnumber, 0, 0,
-                                           false, false, false, QString::null,
+                                           false, false, false, freq_id,
                                            QString::null, "Default", xmltvid);
                 ChannelUtil::UpdateIPTVTuningData(chanid, (*it).m_tuning);
             }
This patch causes the IPTV signal monitor to wait until the channel change script returns with a good (zero) return value before allowing playback to begin.

Code: Select all

--- libs/libmythtv/recorders/iptvsignalmonitor.cpp.orig 2017-01-14 20:10:30.666707790 -0500
+++ libs/libmythtv/recorders/iptvsignalmonitor.cpp      2017-01-14 20:34:15.164221747 -0500
@@ -83,12 +83,20 @@
     if (!running || exit)
         return;

-    if (!m_locked && GetIPTVChannel()->IsOpen())
     {
+        // Don't continue until the external channel
+        // change script returns a good status
         QMutexLocker locker(&statusLock);
-        signalLock.SetValue(1);
-        signalStrength.SetValue(100);
-        m_locked = true;
+        SignalMonitor::UpdateValues();
+        if (!scriptStatus.IsGood())
+            return;
+
+        if (!m_locked && GetIPTVChannel()->IsOpen())
+        {
+            signalLock.SetValue(1);
+            signalStrength.SetValue(100);
+            m_locked = true;
+        }
     }

     EmitStatus();
As a final step you need to add your script to the database directly. First, find the ID of your "FREEBOX" recorder in the database. Please please please backup your database before doing things like this:

Code: Select all

# mysql -u root mythconverg

MariaDB [mythconverg]> select cardid,cardtype from capturecard;
+--------+-----------+
| cardid | cardtype  |
+--------+-----------+
|      1 | HDHOMERUN |
|      3 | HDHOMERUN |
|      6 | FREEBOX   |
+--------+-----------+
3 rows in set (0.00 sec)
In this example we see that my IPTV recorder is ID 6, so simply update the DB with our channel change script for recorder 6:

Code: Select all

MariaDB [mythconverg]> update capturecard set externalcommand="/home/mythtv/stb_ch.sh" where cardid=6;
Next, you must rerun the IPTV channel scanner to ensure the channels get updated with the freq_ids.

That should be it. Please post if you find problems with this patch as I have not been running this setup very long. If I broke something I probably haven't noticed yet :D.

Additional Patches
I had the problem described in TRAC ticket 12773 https://code.mythtv.org/trac/ticket/12773. Channel patch or not, the backend would crash after tuning to the IPTV stream in LiveTV 2 to 3 times. The patch below is basically the patch in the ticket and also resolved this problem for me. All credit goes to the author of this patch:

Code: Select all

--- libs/libmythtv/recorders/iptvchannel.cpp.orig       2017-01-14 20:10:22.876760184 -0500
+++ libs/libmythtv/recorders/iptvchannel.cpp    2017-01-14 20:31:06.408488089 -0500
@@ -71,8 +71,10 @@
         if (sd)
             m_stream_handler->AddListener(sd);

-        if (m_stream_data)
+        if (m_stream_data) {
             m_stream_handler->RemoveListener(m_stream_data);
+            m_stream_data = NULL;
+        }
     }
     else if (sd)
     {
@@ -122,8 +124,10 @@

     if (m_stream_handler)
     {
-        if (m_stream_data)
+        if (m_stream_data) {
             m_stream_handler->RemoveListener(m_stream_data);
+            m_stream_data = NULL;
+        }

         HLSStreamHandler* hsh = dynamic_cast<HLSStreamHandler*>(m_stream_handler);
         HTTPTSStreamHandler* httpsh = dynamic_cast<HTTPTSStreamHandler*>(m_stream_handler);
Finally, when the channel scanner runs or even when you tune IPTV a test runs to check if you have a HLS playlist. This only runs if you connect to the device via http or https and it downloads up to 10MB of data from the encoder to test. Unfortunately, it does this for each channel scanned and when using one of these encoders you are streaming everything from the same device. The result was literally a "MythTV DoS" against my encoder when I ran the scanner to go though all 500 channels in my playlist pointing at the same URL. My encoder didn't appreciate this much.

To resolve this problem, we can disable this HLS check, however as I read the source code this will also disable HLS support. This is also outlined in TRAC ticket 12856 https://code.mythtv.org/trac/ticket/12856. If you're still having issues with backend crashes after applying the patch above this might help as well.

Code: Select all

--- libs/libmythtv/iptvtuningdata.h.orig        2017-01-14 20:10:57.537527061 -0500
+++ libs/libmythtv/iptvtuningdata.h     2017-01-14 20:38:47.703392580 -0500
@@ -220,6 +220,8 @@
   protected:
     bool IsHLSPlaylist(void)
     {
+        // Disable HLS Playlist checking
+        return false;
         if (!qApp)
         {
             LOG(VB_GENERAL, LOG_ERR, QString("IsHLSPlaylist - No QApplication!!"));
A little about RTSP support
Yes, I'm still rambling in this insanely long forum post. While screwing around with this thing I gave RTSP a shot and could not get it to work. Reading the source code revealed to me that MythTV's RTSP support seems to be very limited and will not work work with these devices. You can see in the below wireshark screenshot the RTSP reply from the device to the DESCRIBE query from MythTV:

https://drive.google.com/file/d/0B9y3Av ... sp=sharing

You can see that the device wants to send two separate RTP streams, RTP type 96 for the video and type 97 for the audio. I'm fairly sure MythTV (via FFmpeg?) is capable of playing this back, but the current RTSP implementation in MythTV does not appear capable of handling it. I think it was written for a specific device, and it makes some assumptions which are certainly incorrect in this case:

In CetonRTSP::Describe()

Code: Select all

foreach (QString line, lines)
    {
        if (line.startsWith("m="))
        {
            if (found)
            {
                // another new stream, no need to parse further
                break;
            }
            if (!line.startsWith("m=video"))
            {
                // not a video stream
                continue;
            }
            QStringList args = line.split(" ");
            if (args[2] == "RTP/AVP" && args[3] == "33")
            {
                found = true;
            }
            continue;
        }
        if (line.startsWith("c="))
        {
            // TODO, connection parameter
            // assume we will always get a control entry
            continue;
        }
        if (line.startsWith("a=control:"))
        {
            // Per RFC: a=control:rtsp://example.com/foo
            // This attribute may contain either relative and absolute URLs,
            // following the rules and conventions set out in RFC 1808 [25].
            QString url = line.mid(10).trimmed();
            _controlUrl = url;
            if (url == "*")
            {
                _controlUrl = base;
            }
            else if (_controlUrl.isRelative())
            {
                _controlUrl = base.resolved(_controlUrl);
            }
            continue;
        }
    }
It seems to assume here that the RTP type will never be anything other then 33 and that anything that's not a video stream can be ignored. Extending the parsing to see both streams wouldn't be that difficult but I think extending it to retrieve and playback both streams is beyond my abilities. This goes along with the general feature request of more direct support for these recorders that the OP made.
Post Reply