CetonStreamHandler::CetonStreamHandler(const QString &device) :
    IPTVStreamHandler(IPTVTuningData("", 0, IPTVTuningData::kNone, "", 0, "", 0)),
    _card(0),
    _tuner(0),
    _using_cablecard(false),
    _connected(false),
    _valid(false),
    _last_frequency(0),
    _last_program(0)
{
    setObjectName("CetonStreamHandler");

    QStringList parts = device.split("-");
    if (parts.size() != 2)
    {
        LOG(VB_GENERAL, LOG_ERR, LOC +
            QString("Invalid device id %1").arg(_device));
        return;
    }
    _ip_address = parts.at(0);

    QStringList tuner_parts = parts.at(1).split(".");
    if (tuner_parts.size() == 2)
    {
        _card = tuner_parts.at(0).toUInt();
        _tuner = tuner_parts.at(1).toUInt();
    }
    else
    {
        LOG(VB_GENERAL, LOG_ERR, LOC +
            QString("Invalid device id %1").arg(_device));
        return;
    }

    if (GetVar("diag", "Host_IP_Address") == "")
    {
        LOG(VB_GENERAL, LOG_ERR, LOC +
            "Ceton tuner does not seem to be available at IP");
        return;
    }

    int rtspPort = 8554;
    QString url = QString("rtsp://%1:%2/cetonmpeg%3")
        .arg(_ip_address).arg(rtspPort).arg(_tuner);
    m_tuning = IPTVTuningData(url, 0, IPTVTuningData::kNone, "", 0, "", 0);
    m_use_rtp_streaming = true;

    _valid = true;

    QString cardstatus = GetVar("cas", "CardStatus");
    _using_cablecard = cardstatus == "Inserted";

    if (!_info_queried.contains(_ip_address))
    {
        QString sernum = GetVar("diag", "Host_Serial_Number");
        QString firmware_ver = GetVar("diag", "Host_Firmware");
        QString hardware_ver = GetVar("diag", "Hardware_Revision");

        LOG(VB_RECORD, LOG_INFO, LOC +
            QString("Ceton device %1 initialized. SN: %2, "
                    "Firmware ver. %3, Hardware ver. %4")
            .arg(_ip_address).arg(sernum).arg(firmware_ver).arg(hardware_ver));

        if (_using_cablecard)
        {
            QString brand = GetVar("cas", "CardManufacturer");
            QString auth = GetVar("cas", "CardAuthorization");

            LOG(VB_RECORD, LOG_INFO, LOC +
                QString("Cable card installed (%1) - %2").arg(brand).arg(auth));
        }
        else
        {
            LOG(VB_RECORD, LOG_INFO, LOC +
                "Cable card NOT installed (operating in QAM tuner mode)");
        }

        _info_queried.insert(_ip_address, true);
    }
}
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();
}
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();
}
Exemple #4
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();
}