Beispiel #1
0
bool IPTVChannel::Tune(const IPTVTuningData &tuning)
{
    QMutexLocker locker(&m_lock);

    LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Tune(%1)")
        .arg(tuning.GetDeviceName()));

    if (tuning.GetDataURL().scheme().toUpper() == "RTSP")
    {
        // TODO get RTP info using RTSP
    }

    if (!tuning.IsValid())
    {
        LOG(VB_CHANNEL, LOG_ERR, LOC + QString("Invalid tuning info %1")
            .arg(tuning.GetDeviceName()));
        return false;
    }

    if (m_last_tuning == tuning)
    {
        LOG(VB_CHANNEL, LOG_DEBUG, LOC + QString("Already tuned to %1")
            .arg(tuning.GetDeviceName()));
        return true;
    }

    m_last_tuning = tuning;

    if (!m_firsttune) // for historical reason, an initial tune is
                      // requested at startup so don't open the stream
                      // handler just yet it will be opened after the
                      // next Tune or SetStreamData)
    {
        MPEGStreamData *tmp = m_stream_data;

        CloseStreamHandler();
        if (tmp)
            SetStreamData(tmp);
        else
            OpenStreamHandler();
    }

    m_firsttune = false;

    return true;
}
IPTVStreamHandler::IPTVStreamHandler(const IPTVTuningData &tuning) :
    StreamHandler(tuning.GetDeviceKey()),
    m_tuning(tuning),
    m_write_helper(NULL),
    m_buffer(NULL),
    m_use_rtp_streaming(true)
{
    memset(m_sockets, 0, sizeof(m_sockets));
    memset(m_read_helpers, 0, sizeof(m_read_helpers));
    m_use_rtp_streaming = m_tuning.GetDataURL().scheme().toUpper() == "RTP";
}
IPTVStreamHandler::IPTVStreamHandler(const IPTVTuningData &tuning, int inputid)
    : StreamHandler(tuning.GetDeviceKey(), inputid)
    , m_tuning(tuning)
    , m_write_helper(nullptr)
    , m_buffer(nullptr)
    , m_rtsp_rtp_port(0)
    , m_rtsp_rtcp_port(0)
    , m_rtsp_ssrc(0)
{
    memset(m_sockets, 0, sizeof(m_sockets));
    memset(m_read_helpers, 0, sizeof(m_read_helpers));
    m_use_rtp_streaming = m_tuning.IsRTP();
}
void IPTVStreamHandler::run(void)
{
    RunProlog();

    LOG(VB_GENERAL, LOG_INFO, LOC + "run()");

    SetRunning(true, false, false);

    // TODO Error handling..

    // Setup
    CetonRTSP *rtsp = NULL;
    IPTVTuningData tuning = m_tuning;
    if (m_tuning.GetURL(0).scheme().toLower() == "rtsp")
    {
        rtsp = new CetonRTSP(m_tuning.GetURL(0));

        // Check RTSP capabilities
        QStringList options;
        if (!(rtsp->GetOptions(options)     && options.contains("OPTIONS")  &&
              options.contains("DESCRIBE")  && options.contains("SETUP")    &&
              options.contains("PLAY")      && options.contains("TEARDOWN")))
        {
            LOG(VB_RECORD, LOG_ERR, LOC +
                "RTSP interface did not support the necessary options");
            delete rtsp;
            SetRunning(false, false, false);
            RunEpilog();
            return;
        }

        if (!rtsp->Describe())
        {
            LOG(VB_RECORD, LOG_ERR, LOC +
                "RTSP Describe command failed");
            delete rtsp;
            SetRunning(false, false, false);
            RunEpilog();
            return;
        }

        tuning = IPTVTuningData(
            QString("rtp://%1@%2:0")
            .arg(m_tuning.GetURL(0).host())
            .arg(QHostAddress(QHostAddress::Any).toString()), 0,
            IPTVTuningData::kNone,
            QString("rtp://%1@%2:0")
            .arg(m_tuning.GetURL(0).host())
            .arg(QHostAddress(QHostAddress::Any).toString()), 0,
            "", 0);
    }

    for (uint i = 0; i < IPTV_SOCKET_COUNT; i++)
    {
        QUrl url = tuning.GetURL(i);
        if (url.port() < 0)
            continue;

        m_sockets[i] = new QUdpSocket();
        m_read_helpers[i] = new IPTVStreamHandlerReadHelper(
            this, m_sockets[i], i);

        // we need to open the descriptor ourselves so we
        // can set some socket options
        int fd = socket(AF_INET, SOCK_DGRAM, 0); // create IPv4 socket
        if (fd < 0)
        {
            LOG(VB_GENERAL, LOG_ERR, LOC +
                "Unable to create socket " + ENO);
            continue;
        }
        int buf_size = 2 * 1024 * max(tuning.GetBitrate(i)/1000, 500U);
        if (!tuning.GetBitrate(i))
            buf_size = 2 * 1024 * 1024;
        int ok = setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
                            (char *)&buf_size, sizeof(buf_size));
        if (ok)
        {
            LOG(VB_GENERAL, LOG_INFO, LOC +
                QString("Increasing buffer size to %1 failed")
                .arg(buf_size) + ENO);
        }
        /*
          int broadcast = 1;
          ok = setsockopt(fd, SOL_SOCKET, SO_BROADCAST,
          (char *)&broadcast, sizeof(broadcast));
          if (ok)
          {
          LOG(VB_GENERAL, LOG_INFO, LOC +
          QString("Enabling broadcast failed") + ENO);
          }
        */
        m_sockets[i]->setSocketDescriptor(
            fd, QAbstractSocket::UnconnectedState, QIODevice::ReadOnly);

        m_sockets[i]->bind(QHostAddress::Any, url.port());

        QHostAddress dest_addr(tuning.GetURL(i).host());

        if (dest_addr != QHostAddress::Any)
        {
            //m_sockets[i]->joinMulticastGroup(dest_addr); // needs Qt 4.8
            LOG(VB_GENERAL, LOG_INFO, LOC + QString("Joining %1")
                .arg(dest_addr.toString()));
            struct ip_mreq imr;
            memset(&imr, 0, sizeof(struct ip_mreq));
            imr.imr_multiaddr.s_addr = inet_addr(
                dest_addr.toString().toLatin1().constData());
            imr.imr_interface.s_addr = htonl(INADDR_ANY);
            if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
				(const char *)&imr, sizeof(imr)) < 0)
            {
                LOG(VB_GENERAL, LOG_ERR, LOC +
                    "setsockopt - IP_ADD_MEMBERSHIP " + ENO);
            }
        }

        if (!url.userInfo().isEmpty())
            m_sender[i] = QHostAddress(url.userInfo());
    }
    if (m_use_rtp_streaming)
        m_buffer = new RTPPacketBuffer(tuning.GetBitrate(0));
    else
        m_buffer = new UDPPacketBuffer(tuning.GetBitrate(0));
    m_write_helper = new IPTVStreamHandlerWriteHelper(this);
    m_write_helper->Start();

    bool error = false;
    if (rtsp)
    {
        // Start Streaming
        if (!rtsp->Setup(m_sockets[0]->localPort(),
                         m_sockets[1]->localPort()) ||
            !rtsp->Play())
        {
            LOG(VB_RECORD, LOG_ERR, LOC +
                "Starting recording (RTP initialization failed). Aborting.");
            error = true;
        }
    }

    if (!error)
    {
        // Enter event loop
        exec();
    }

    // Clean up
    for (uint i = 0; i < IPTV_SOCKET_COUNT; i++)
    {
        if (m_sockets[i])
        {
            delete m_sockets[i];
            m_sockets[i] = NULL;
            delete m_read_helpers[i];
            m_read_helpers[i] = NULL;
        }
    }
    delete m_buffer;
    m_buffer = NULL;
    delete m_write_helper;
    m_write_helper = NULL;

    if (rtsp)
    {
        rtsp->Teardown();
        delete rtsp;
    }

    SetRunning(false, false, false);
    RunEpilog();
}
void IPTVStreamHandler::run(void)
{
    RunProlog();

    LOG(VB_GENERAL, LOG_INFO, LOC + "run()");

    SetRunning(true, false, false);

    // TODO Error handling..

    // Setup
    CetonRTSP *rtsp = nullptr;
    IPTVTuningData tuning = m_tuning;
    if(m_tuning.IsRTSP())
    {
        rtsp = new CetonRTSP(m_tuning.GetURL(0));

        // Check RTSP capabilities
        QStringList options;
        if (!(rtsp->GetOptions(options)     && options.contains("DESCRIBE") &&
              options.contains("SETUP")     && options.contains("PLAY")     &&
              options.contains("TEARDOWN")))
        {
            LOG(VB_RECORD, LOG_ERR, LOC +
                "RTSP interface did not support the necessary options");
            delete rtsp;
            SetRunning(false, false, false);
            RunEpilog();
            return;
        }

        if (!rtsp->Describe())
        {
            LOG(VB_RECORD, LOG_ERR, LOC +
                "RTSP Describe command failed");
            delete rtsp;
            SetRunning(false, false, false);
            RunEpilog();
            return;
        }

        m_use_rtp_streaming = true;

        QUrl urltuned = m_tuning.GetURL(0);
        urltuned.setScheme("rtp");
        urltuned.setPort(0);
        tuning = IPTVTuningData(urltuned.toString(), 0, IPTVTuningData::kNone,
                                urltuned.toString(), 0, "", 0);
    }

    bool error = false;

    int start_port = 0;
    for (uint i = 0; i < IPTV_SOCKET_COUNT; i++)
    {
        QUrl url = tuning.GetURL(i);
        if (url.port() < 0)
            continue;

        LOG(VB_RECORD, LOG_DEBUG, LOC +
            QString("setting up url[%1]:%2").arg(i).arg(url.toString()));

        // always ensure we use consecutive port numbers
        int port = start_port ? start_port + 1 : url.port();
        QString host = url.host();
        QHostAddress dest_addr(host);

        if (!host.isEmpty() && dest_addr.isNull())
        {
            // address is a hostname, attempts to resolve it
            QHostInfo info = QHostInfo::fromName(host);
            QList<QHostAddress> list = info.addresses();

            if (list.isEmpty())
            {
                LOG(VB_RECORD, LOG_ERR, LOC +
                    QString("Can't resolve hostname:'%1'").arg(host));
            }
            else
            {
                for (int j=0; j < list.size(); j++)
                {
                    dest_addr = list[j];
                    if (list[j].protocol() == QAbstractSocket::IPv6Protocol)
                    {
                        // We prefer first IPv4
                        break;
                    }
                }
                LOG(VB_RECORD, LOG_DEBUG, LOC +
                    QString("resolved %1 as %2").arg(host).arg(dest_addr.toString()));
            }
        }
        bool ipv6 = dest_addr.protocol() == QAbstractSocket::IPv6Protocol;
        bool is_multicast = ipv6 ?
            dest_addr.isInSubnet(QHostAddress::parseSubnet("ff00::/8")) :
            (dest_addr.toIPv4Address() & 0xf0000000) == 0xe0000000;

        m_sockets[i] = new QUdpSocket();
        if (!is_multicast)
        {
            // this allow to filter incoming traffic, and make sure it's from
            // the requested server
            m_sender[i] = dest_addr;
        }
        m_read_helpers[i] = new IPTVStreamHandlerReadHelper(
            this, m_sockets[i], i);

        // we need to open the descriptor ourselves so we
        // can set some socket options
        int fd = socket(ipv6 ? AF_INET6 : AF_INET, SOCK_DGRAM, 0); // create IPv4 socket
        if (fd < 0)
        {
            LOG(VB_GENERAL, LOG_ERR, LOC +
                "Unable to create socket " + ENO);
            continue;
        }
        int buf_size = 2 * 1024 * max(tuning.GetBitrate(i)/1000, 500U);
        if (!tuning.GetBitrate(i))
            buf_size = 2 * 1024 * 1024;
        int err = setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
                            (char *)&buf_size, sizeof(buf_size));
        if (err)
        {
            LOG(VB_GENERAL, LOG_INFO, LOC +
                QString("Increasing buffer size to %1 failed")
                .arg(buf_size) + ENO);
        }

        m_sockets[i]->setSocketDescriptor(
            fd, QAbstractSocket::UnconnectedState, QIODevice::ReadOnly);

        // we bind to destination address if it's a multicast address, or
        // the local ones otherwise
        if (!m_sockets[i]->bind(is_multicast ?
                                dest_addr :
                                (ipv6 ? QHostAddress::AnyIPv6 : QHostAddress::Any),
                                port))
        {
            LOG(VB_GENERAL, LOG_ERR, LOC + "Binding to port failed.");
            error = true;
        }
        else
        {
            start_port = m_sockets[i]->localPort();
        }

        if (is_multicast)
        {
            m_sockets[i]->joinMulticastGroup(dest_addr);
            LOG(VB_GENERAL, LOG_INFO, LOC + QString("Joining %1")
                .arg(dest_addr.toString()));
        }

        if (!is_multicast && rtsp && i == 1)
        {
            m_rtcp_dest = dest_addr;
        }
    }

    if (!error)
    {
        if (m_tuning.IsRTP() || m_tuning.IsRTSP())
            m_buffer = new RTPPacketBuffer(tuning.GetBitrate(0));
        else
            m_buffer = new UDPPacketBuffer(tuning.GetBitrate(0));
        m_write_helper =
            new IPTVStreamHandlerWriteHelper(this);
        m_write_helper->Start();
    }

    if (!error && rtsp)
    {
        // Start Streaming
        if (!rtsp->Setup(m_sockets[0]->localPort(), m_sockets[1]->localPort(),
                         m_rtsp_rtp_port, m_rtsp_rtcp_port, m_rtsp_ssrc) ||
            !rtsp->Play())
        {
            LOG(VB_RECORD, LOG_ERR, LOC +
                "Starting recording (RTP initialization failed). Aborting.");
            error = true;
        }
        if (m_rtsp_rtcp_port > 0)
        {
            m_write_helper->SendRTCPReport();
            m_write_helper->StartRTCPRR();
        }
    }

    if (!error)
    {
        // Enter event loop
        exec();
    }

    // Clean up
    for (uint i = 0; i < IPTV_SOCKET_COUNT; i++)
    {
        if (m_sockets[i])
        {
            delete m_sockets[i];
            m_sockets[i] = nullptr;
            delete m_read_helpers[i];
            m_read_helpers[i] = nullptr;
        }
    }
    delete m_buffer;
    m_buffer = nullptr;
    delete m_write_helper;
    m_write_helper = nullptr;

    if (rtsp)
    {
        rtsp->Teardown();
        delete rtsp;
    }

    SetRunning(false, false, false);
    RunEpilog();
}
Beispiel #6
0
void IPTVStreamHandler::run(void)
{
    RunProlog();

    LOG(VB_GENERAL, LOG_INFO, LOC + "run()");

    SetRunning(true, false, false);

    // TODO Error handling..

    // Setup
    CetonRTSP *rtsp = NULL;
    IPTVTuningData tuning = m_tuning;
    if (m_tuning.GetURL(0).scheme().toLower() == "rtsp")
    {
        rtsp = new CetonRTSP(m_tuning.GetURL(0));

        // Check RTSP capabilities
        QStringList options;
        if (!(rtsp->GetOptions(options)     && options.contains("OPTIONS")  &&
              options.contains("DESCRIBE")  && options.contains("SETUP")    &&
              options.contains("PLAY")      && options.contains("TEARDOWN")))
        {
            LOG(VB_RECORD, LOG_ERR, LOC +
                "RTSP interface did not support the necessary options");
            delete rtsp;
            SetRunning(false, false, false);
            RunEpilog();
            return;
        }

        if (!rtsp->Describe())
        {
            LOG(VB_RECORD, LOG_ERR, LOC +
                "RTSP Describe command failed");
            delete rtsp;
            SetRunning(false, false, false);
            RunEpilog();
            return;
        }

        tuning = IPTVTuningData(
            QString("rtp://%1@%2:0")
            .arg(m_tuning.GetURL(0).host())
            .arg(QHostAddress(QHostAddress::Any).toString()), 0,
            IPTVTuningData::kNone,
            QString("rtp://%1@%2:0")
            .arg(m_tuning.GetURL(0).host())
            .arg(QHostAddress(QHostAddress::Any).toString()), 0,
            "", 0);
    }

    for (uint i = 0; i < IPTV_SOCKET_COUNT; i++)
    {
        QUrl url = tuning.GetURL(i);
        if (url.port() < 0)
            continue;

        m_sockets[i] = new QTcpSocket();
		m_sockets[i]->setSocketOption(QAbstractSocket::LowDelayOption, 1);
        m_read_helpers[i] = new IPTVStreamHandlerReadHelper(
            this, m_sockets[i], i);

        if (!url.userInfo().isEmpty())
            m_sender[i] = QHostAddress(url.userInfo());

        m_sockets[i]->connectToHost(url.host().toAscii(), 3000);
 if (m_sockets[i]->waitForConnected(1000))
   {
 m_sockets[i]->write("GET " + url.path().toAscii() + " HTTP/1.0\r\n\r\n\r\n\r\n");
                           m_sockets[i]->waitForBytesWritten(500);
                
}
else
{
  qDebug("not Connected!");
    m_sockets[i]->connectToHost(url.host().toAscii(), 3000);
m_sockets[i]->write("GET " + url.path().toAscii() + " HTTP/1.0\r\n\r\n\r\n\r\n");
                           m_sockets[i]->waitForBytesWritten(500);
}
                          
						   
						 
    }
    //if (m_use_rtp_streaming)
      //  m_buffer = new RTPPacketBuffer(tuning.GetBitrate(0));
    //else
        m_buffer = new UDPPacketBuffer(tuning.GetBitrate(0));
    m_write_helper = new IPTVStreamHandlerWriteHelper(this);
    m_write_helper->Start();

    bool error = false;
    /*if (rtsp)
    {
        // Start Streaming
        if (!rtsp->Setup(m_sockets[0]->localPort(),
                         m_sockets[1]->localPort()) ||
            !rtsp->Play())
        {
            LOG(VB_RECORD, LOG_ERR, LOC +
                "Starting recording (RTP initialization failed). Aborting.");
            error = true;
        }
    }
*/
    if (!error)
    {
        // Enter event loop
        exec();
    }

    // Clean up
    for (uint i = 0; i < IPTV_SOCKET_COUNT; i++)
    {
        if (m_sockets[i])
        {
            delete m_sockets[i];
            m_sockets[i] = NULL;
            delete m_read_helpers[i];
            m_read_helpers[i] = NULL;
        }
    }
    delete m_buffer;
    m_buffer = NULL;
    delete m_write_helper;
    m_write_helper = NULL;

    if (rtsp)
    {
        rtsp->Teardown();
        delete rtsp;
    }

    SetRunning(false, false, false);
    RunEpilog();
}