00001
00006 #define _INC_ERRNO
00007
00008 #include <algorithm>
00009
00010 #include "iptvfeederudp.h"
00011
00012
00013 #include <QUrl>
00014
00015
00016 #include <BasicUsageEnvironment.hh>
00017 #include <Groupsock.hh>
00018 #include <GroupsockHelper.hh>
00019 #include <BasicUDPSource.hh>
00020 #include <TunnelEncaps.hh>
00021
00022
00023 #include "iptvmediasink.h"
00024 #include "mythcontext.h"
00025 #include "mythlogging.h"
00026 #include "tspacket.h"
00027
00028 #define LOC QString("IPTVFeedUDP: ")
00029
00030 IPTVFeederUDP::IPTVFeederUDP() :
00031 _source(NULL),
00032 _sink(NULL)
00033 {
00034 LOG(VB_RECORD, LOG_INFO, LOC + "ctor -- success");
00035 }
00036
00037 IPTVFeederUDP::~IPTVFeederUDP()
00038 {
00039 LOG(VB_RECORD, LOG_INFO, LOC + "dtor -- begin");
00040 Close();
00041 LOG(VB_RECORD, LOG_INFO, LOC + "dtor -- end");
00042 }
00043
00044 bool IPTVFeederUDP::IsUDP(const QString &url)
00045 {
00046 return url.startsWith("udp://", Qt::CaseInsensitive);
00047 }
00048
00049 bool IPTVFeederUDP::Open(const QString &url)
00050 {
00051 LOG(VB_RECORD, LOG_INFO, LOC + QString("Open(%1) -- begin").arg(url));
00052
00053 QMutexLocker locker(&_lock);
00054
00055 if (_source)
00056 {
00057 LOG(VB_RECORD, LOG_INFO, LOC + "Open() -- end 1");
00058 return true;
00059 }
00060
00061 QUrl parse(url);
00062 if (!parse.isValid() || parse.host().isEmpty() || (-1 == parse.port()))
00063 {
00064 LOG(VB_RECORD, LOG_INFO, LOC + "Open() -- end 2");
00065 return false;
00066 }
00067
00068 struct in_addr addr;
00069 QByteArray host = parse.host().toLatin1();
00070 addr.s_addr = our_inet_addr(host.constData());
00071
00072
00073 if (!InitEnv())
00074 return false;
00075
00076 ReceivingSocketAddr = our_inet_addr(parse.host().toLatin1());
00077
00078 Groupsock *socket = new Groupsock(*_live_env, addr, parse.port(), 0);
00079 if (!socket)
00080 {
00081 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create Live UDP Socket.");
00082 FreeEnv();
00083 return false;
00084 }
00085 _source = BasicUDPSource::createNew(*_live_env, socket);
00086 if (!_source)
00087 {
00088 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create Live UDP 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 IPTVFeederUDP::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->gs();
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 IPTVFeederUDP::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 IPTVFeederUDP::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 }