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
.
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.