00001
00006 #include <algorithm>
00007
00008 #include "iptvfeederrtp.h"
00009
00010
00011 #include <QUrl>
00012
00013
00014 #include <BasicUsageEnvironment.hh>
00015 #include <Groupsock.hh>
00016 #include <GroupsockHelper.hh>
00017 #include <SimpleRTPSource.hh>
00018 #include <TunnelEncaps.hh>
00019
00020
00021 #include "iptvmediasink.h"
00022 #include "mythcontext.h"
00023 #include "mythlogging.h"
00024 #include "tspacket.h"
00025
00026 #define LOC QString("IPTVFeedRTP: ")
00027
00028 IPTVFeederRTP::IPTVFeederRTP() :
00029 _source(NULL),
00030 _sink(NULL)
00031 {
00032 LOG(VB_RECORD, LOG_INFO, LOC + "ctor -- success");
00033 }
00034
00035 IPTVFeederRTP::~IPTVFeederRTP()
00036 {
00037 LOG(VB_RECORD, LOG_INFO, LOC + "dtor -- begin");
00038 Close();
00039 LOG(VB_RECORD, LOG_INFO, LOC + "dtor -- end");
00040 }
00041
00042 bool IPTVFeederRTP::IsRTP(const QString &url)
00043 {
00044 return url.startsWith("rtp://", Qt::CaseInsensitive);
00045 }
00046
00047 bool IPTVFeederRTP::Open(const QString &url)
00048 {
00049 LOG(VB_RECORD, LOG_INFO, LOC + QString("Open(%1) -- begin").arg(url));
00050
00051 QMutexLocker locker(&_lock);
00052
00053 if (_source)
00054 {
00055 LOG(VB_RECORD, LOG_INFO, LOC + "Open() -- end 1");
00056 return true;
00057 }
00058
00059 QUrl parse(url);
00060 if (!parse.isValid() || parse.host().isEmpty() || (-1 == parse.port()))
00061 {
00062 LOG(VB_RECORD, LOG_INFO, LOC + "Open() -- end 2");
00063 return false;
00064 }
00065
00066 struct in_addr addr;
00067 QByteArray host = parse.host().toLatin1();
00068 addr.s_addr = our_inet_addr(host.constData());
00069
00070
00071 if (!InitEnv())
00072 return false;
00073
00074 ReceivingSocketAddr = our_inet_addr(parse.host().toLatin1());
00075
00076 Groupsock *socket = new Groupsock(*_live_env, addr, parse.port(), 0);
00077 if (!socket)
00078 {
00079 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create Live RTP Socket.");
00080 FreeEnv();
00081 return false;
00082 }
00083
00084 _source = SimpleRTPSource::createNew(*_live_env, socket, 33, 90000,
00085 "video/MP2T", 0, False);
00086 if (!_source)
00087 {
00088 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create Live RTP Source.");
00089
00090 if (socket)
00091 delete socket;
00092
00093 FreeEnv();
00094 return false;
00095 }
00096
00097 _sink = IPTVMediaSink::CreateNew(*_live_env, TSPacket::kSize * 128*1024);
00098 if (!_sink)
00099 {
00100 LOG(VB_GENERAL, LOG_ERR, QString("IPTV # Failed to create sink: %1")
00101 .arg(_live_env->getResultMsg()));
00102
00103 Medium::close(_source);
00104 _source = NULL;
00105 if (socket)
00106 delete socket;
00107 FreeEnv();
00108
00109 return false;
00110 }
00111
00112 _sink->startPlaying(*_source, NULL, NULL);
00113 vector<TSDataListener*>::iterator it = _listeners.begin();
00114 for (; it != _listeners.end(); ++it)
00115 _sink->AddListener(*it);
00116
00117 LOG(VB_RECORD, LOG_INFO, LOC + "Open() -- end");
00118
00119 return true;
00120 }
00121
00122 void IPTVFeederRTP::Close(void)
00123 {
00124 LOG(VB_RECORD, LOG_INFO, LOC + "Close() -- begin");
00125 Stop();
00126
00127 QMutexLocker locker(&_lock);
00128
00129 if (_sink)
00130 {
00131 Medium::close(_sink);
00132 _sink = NULL;
00133 }
00134
00135 if (_source)
00136 {
00137 Groupsock *socket = _source->RTPgs();
00138 Medium::close(_source);
00139 _source = NULL;
00140 if (socket)
00141 delete socket;
00142 }
00143
00144 FreeEnv();
00145
00146 LOG(VB_RECORD, LOG_INFO, LOC + "Close() -- end");
00147 }
00148
00149 void IPTVFeederRTP::AddListener(TSDataListener *item)
00150 {
00151 LOG(VB_RECORD, LOG_INFO, LOC + QString("AddListener(0x%1) -- begin")
00152 .arg((uint64_t)item,0,16));
00153 if (!item)
00154 {
00155 LOG(VB_RECORD, LOG_INFO, LOC + QString("AddListener(0x%1) -- end")
00156 .arg((uint64_t)item,0,16));
00157 return;
00158 }
00159
00160
00161 RemoveListener(item);
00162
00163
00164 QMutexLocker locker(&_lock);
00165 _listeners.push_back(item);
00166
00167 if (_sink)
00168 _sink->AddListener(item);
00169
00170 LOG(VB_RECORD, LOG_INFO, LOC + QString("AddListener(0x%1) -- end")
00171 .arg((uint64_t)item,0,16));
00172 }
00173
00174 void IPTVFeederRTP::RemoveListener(TSDataListener *item)
00175 {
00176 LOG(VB_RECORD, LOG_INFO, LOC + QString("RemoveListener(0x%1) -- begin")
00177 .arg((uint64_t)item,0,16));
00178 QMutexLocker locker(&_lock);
00179 vector<TSDataListener*>::iterator it =
00180 find(_listeners.begin(), _listeners.end(), item);
00181
00182 if (it == _listeners.end())
00183 {
00184 LOG(VB_RECORD, LOG_INFO, LOC + QString("RemoveListener(0x%1) -- end 1")
00185 .arg((uint64_t)item,0,16));
00186 return;
00187 }
00188
00189
00190 *it = *_listeners.rbegin();
00191 _listeners.resize(_listeners.size() - 1);
00192
00193 if (_sink)
00194 _sink->RemoveListener(item);
00195
00196 LOG(VB_RECORD, LOG_INFO, LOC + QString("RemoveListener(0x%1) -- end 2")
00197 .arg((uint64_t)item,0,16));
00198 }