Exemplo n.º 1
0
bool
MsgChannel::getPacketSync(MsgPacket& out)
{
	std::string header;
	if ( not getLineSync(header, size_t(MsgPacket::limit_type::MAX_HEADER_SIZE)) )
	{
		PWLOGLIB("failed to get line sync");
		return false;
	}

	MsgPacket tmp;
	if ( not tmp.setHeader(header.c_str(), header.size()) )
	{
		PWLOGLIB("failed to set header");
		return false;
	}

	if ( tmp.getBodySize() )
	{
		blob_type& body(tmp.m_body);
		if ( not getDataSync(const_cast<char*>(body.buf), body.size) )
		{
			PWLOGLIB("failed to sync body");
			return false;
		}
	}

	out.swap(tmp);
	return true;
}
Exemplo n.º 2
0
void cLiveStreamer::sendStreamPacket(sStreamPacket *pkt)
{
  bool bReady = IsReady();

  if(!bReady || pkt == NULL || pkt->size == 0)
    return;

  // Send stream information as the first packet on startup
  if (IsStarting() && bReady)
  {
    // wait for first I-Frame (if enabled)
    if(m_waitforiframe && pkt->frametype != cStreamInfo::ftIFRAME) {
      return;
    }

    INFOLOG("streaming of channel started");
    m_last_tick.Set(0);
    m_requestStreamChange = true;
    m_startup = false;
  }

  // send stream change on demand
  if(m_requestStreamChange)
    sendStreamChange();

  // if a audio or video packet was sent, the signal is restored
  if(m_SignalLost && (pkt->content == cStreamInfo::scVIDEO || pkt->content == cStreamInfo::scAUDIO)) {
    INFOLOG("signal restored");
    sendStatus(XVDR_STREAM_STATUS_SIGNALRESTORED);
    m_SignalLost = false;
    m_requestStreamChange = true;
    m_last_tick.Set(0);
    return;
  }

  if(m_SignalLost)
    return;

  // initialise stream packet
  MsgPacket* packet = new MsgPacket(XVDR_STREAM_MUXPKT, XVDR_CHANNEL_STREAM);
  packet->disablePayloadCheckSum();

  // write stream data
  packet->put_U16(pkt->pid);
  packet->put_S64(pkt->pts);
  packet->put_S64(pkt->dts);
  if(m_protocolVersion >= 5) {
    packet->put_U32(pkt->duration);
  }

  // write frame type into unused header field clientid
  packet->setClientID((uint16_t)pkt->frametype);

  // write payload into stream packet
  packet->put_U32(pkt->size);
  packet->put_Blob(pkt->data, pkt->size);

  m_Queue->Add(packet);
  m_last_tick.Set(0);
}
Exemplo n.º 3
0
bool cLiveQueue::Pause(bool on)
{
  cMutexLock lock(&m_lock);

  // deactivate timeshift
  if(!on)
  {
    m_pause = false;
    m_cond.Signal();
    return true;
  }

  if(m_pause)
    return false;

  // create offline storage
  if(m_readfd == -1)
  {
    m_storage = cString::sprintf("%s/xvdr-ringbuffer-%05i.data", (const char*)TimeShiftDir, m_socket);
    DEBUGLOG("FILE: %s", (const char*)m_storage);

    m_readfd = open(m_storage, O_CREAT | O_RDONLY, 0644);
    m_writefd = open(m_storage, O_CREAT | O_WRONLY, 0644);
    lseek(m_readfd, 0, SEEK_SET);
    lseek(m_writefd, 0, SEEK_SET);

    if(m_readfd == -1) {
      ERRORLOG("Failed to create timeshift ringbuffer !");
    }
  }

  m_pause = true;

  // push all packets from the queue to the offline storage
  DEBUGLOG("Writing %i packets into timeshift buffer", size());

  while(!empty())
  {
    MsgPacket* p = front();

    p->write(m_writefd, 1000);
    delete p;

    pop();
  }

  return true;
}
Exemplo n.º 4
0
Demux::SwitchStatus Demux::SwitchChannel(uint32_t channeluid)
{
  m_client->Log(DEBUG, "changing to channel %d (priority %i)", channeluid, m_priority);

  {
    MutexLock lock(&m_lock);
    m_queuelocked = true;
  }

  CleanupPacketQueue();
  m_cond.Signal();

  MsgPacket vrp(XVDR_CHANNELSTREAM_OPEN);
  vrp.put_U32(channeluid);
  vrp.put_S32(m_priority);
  vrp.put_U8(m_iframestart);

  MsgPacket* vresp = ReadResult(&vrp);

  {
    MutexLock lock(&m_lock);
    m_queuelocked = false;
    m_paused = false;
    m_timeshiftmode = false;

    m_streams.clear();
  }

  SwitchStatus status = SC_OK;

  if(vresp != NULL)
    status = (SwitchStatus)vresp->get_U32();

  delete vresp;

  if(status == SC_OK)
  {
    m_channeluid = channeluid;
    m_client->Log(INFO, "sucessfully switched channel");
  }
  else
    m_client->Log(FAILURE, "%s - failed to set channel (status: %i)", __FUNCTION__, status);

  m_cond.Signal();

  return status;
}
Exemplo n.º 5
0
void cLiveQueue::Action()
{
  INFOLOG("LiveQueue started");

  // wait for first packet
  m_cond.Wait(0);

  while(Running())
  {
    MsgPacket* p = NULL;

    m_lock.Lock();

    // just wait if we are paused
    if(m_pause)
    {
      m_lock.Unlock();
      m_cond.Wait(0);
      m_lock.Lock();
    }

    // check packet queue
    if(size() > 0)
    {
      p = front();
      pop();
    }

    m_lock.Unlock();

    // no packets to send
    if(p == NULL)
    {
      m_cond.Wait(3000);
      continue;
    }
    // send packet
    else {
      p->write(m_socket, 500);
      delete p;
    }

  }

  INFOLOG("LiveQueue stopped");
}
Exemplo n.º 6
0
void MsgHandlerJSON::Run() {
	std::string msg;
	syslog(LOG_INFO, "JSON message handler started");

	m_closed = false;

	while(IsRunning()) {
		// exit if connection was closed
		if(m_closed) {
			break;
		}

		// wait for string
		if(!ReceiveString(msg)) {
			continue;
		}

		std::cout << msg << std::endl;

		// check for http request
		if(msg.substr(0, 8) == "OPTIONS " && msg.size() > 8) {
			msg = msg.substr(8);
		}
		else if(msg.substr(0, 4) != "GET ") {
			continue;
		}

		std::string::size_type p = msg.rfind("HTTP/");

		if(p == std::string::npos) {
			continue;
		}

		msg = msg.substr(0, p);
		std::cout << "URI: " << msg << std::endl;

		// extract JSON query string
		p = msg.find("?");

		std::string url;
		std::string query;

		if(p > 0) {
			url = msg.substr(0, p);
		}

		if(p < msg.size() - 1) {
			query = URLDecode(msg.substr(p + 1));
		}

		std::cout << "URL: " << url << std::endl;
		std::cout << "QUERY: " << query << std::endl;

		// get message id
		while((url[0] > '9' || url[0] < '0') && url.size() > 1) {
			url = url.substr(1);
		}

		uint32_t msgid = atoi(url.c_str());
		MsgPacket* request = MsgPacketFromJSON(query, msgid);

		if(m_msgtype != 0) {
			request->setType(m_msgtype);
		}

		std::cout << "MSGID: " << request->getMsgID() << std::endl;
		std::cout << "MSGTYPE: " << request->getType() << std::endl;

		request->print();

		MsgPacket* response = new MsgPacket(request->getMsgID(), request->getType(), request->getUID());

		std::string jsonformat;
		std::string result;

		request->rewind();

		if(OnMessage(request, response)) {
			if(OnCustomJSONResponse(response, result)) {
				SendHTTPResponse(result);
			}
			else if(OnResponseFormat(response, jsonformat)) {
				result = MsgPacketToJSON(response, jsonformat);
				SendHTTPResponse(result);
			}
		}

		delete response;
		delete request;
	}
}
Exemplo n.º 7
0
void cLiveStreamer::RequestSignalInfo()
{
  cMutexLock lock(&m_DeviceMutex);

  if(!Running() || m_Device == NULL) {
    return;
  }

  // do not send (and pollute the client with) signal information
  // if we are paused
  if(IsPaused())
    return;

  MsgPacket* resp = new MsgPacket(XVDR_STREAM_SIGNALINFO, XVDR_CHANNEL_STREAM);

  int DeviceNumber = m_Device->DeviceNumber() + 1;
  int Strength = 0;
  int Quality = 0;

  if(!TimeShiftMode()) {
    Strength = m_Device->SignalStrength();
    Quality = m_Device->SignalQuality();
  }

  resp->put_String(*cString::sprintf("%s #%d - %s", 
#if VDRVERSNUM < 10728
#warning "VDR versions < 1.7.28 do not support all features"
			"Unknown",
			DeviceNumber,
			"Unknown"));
#else
			(const char*)m_Device->DeviceType(),
			DeviceNumber,
			(const char*)m_Device->DeviceName()));
#endif

  // Quality:
  // 4 - NO LOCK
  // 3 - NO SYNC
  // 2 - NO VITERBI
  // 1 - NO CARRIER
  // 0 - NO SIGNAL

  if(TimeShiftMode())
  {
    resp->put_String("TIMESHIFT");
  }
  else if(Quality == -1)
  {
    resp->put_String("UNKNOWN (Incompatible device)");
    Quality = 0;
  }
  else
    resp->put_String(*cString::sprintf("%s:%s:%s:%s:%s", 
			(Quality > 4) ? "LOCKED" : "-",
			(Quality > 0) ? "SIGNAL" : "-",
			(Quality > 1) ? "CARRIER" : "-",
			(Quality > 2) ? "VITERBI" : "-",
			(Quality > 3) ? "SYNC" : "-"));

  resp->put_U32((Strength << 16 ) / 100);
  resp->put_U32((Quality << 16 ) / 100);
  resp->put_U32(0);
  resp->put_U32(0);

  // get provider & service information
  const cChannel* channel = FindChannelByUID(m_uid);
  if(channel != NULL) {
    // put in provider name
    resp->put_String(channel->Provider());

    // what the heck should be the service name ?
    // using PortalName for now
    resp->put_String(channel->PortalName());
  }
  else {
    resp->put_String("");
    resp->put_String("");
  }

  DEBUGLOG("RequestSignalInfo");
  m_Queue->Add(resp);
}
Exemplo n.º 8
0
void cLiveStreamer::sendStatus(int status)
{
  MsgPacket* packet = new MsgPacket(XVDR_STREAM_STATUS, XVDR_CHANNEL_STREAM);
  packet->put_U32(status);
  m_parent->QueueMessage(packet);
}
Exemplo n.º 9
0
void cLiveStreamer::sendStreamChange()
{
  MsgPacket* resp = new MsgPacket(XVDR_STREAM_CHANGE, XVDR_CHANNEL_STREAM);

  DEBUGLOG("sendStreamChange");

  cChannelCache cache;
  INFOLOG("Stored channel information in cache:");
  for (std::list<cTSDemuxer*>::iterator i = m_Demuxers.begin(); i != m_Demuxers.end(); i++) {
    cache.AddStream(*(*i));
    (*i)->info();
  }
  cChannelCache::AddToCache(m_uid, cache);

  m_FilterMutex.Lock();

  // reorder streams as preferred
  reorderStreams(m_LanguageIndex, m_LangStreamType);

  for (std::list<cTSDemuxer*>::iterator idx = m_Demuxers.begin(); idx != m_Demuxers.end(); idx++)
  {
    cTSDemuxer* stream = (*idx);

    if (stream == NULL)
      continue;

    int streamid = stream->GetPID();
    resp->put_U32(streamid);

    switch(stream->GetContent())
    {
      case cStreamInfo::scAUDIO:
        resp->put_String(stream->TypeName());
        resp->put_String(stream->GetLanguage());
        if(m_protocolVersion >= 5) {
          resp->put_U32(stream->GetChannels());
          resp->put_U32(stream->GetSampleRate());
          resp->put_U32(stream->GetBlockAlign());
          resp->put_U32(stream->GetBitRate());
          resp->put_U32(stream->GetBitsPerSample());
        }
        break;

      case cStreamInfo::scVIDEO:
        resp->put_String(stream->TypeName());
        resp->put_U32(stream->GetFpsScale());
        resp->put_U32(stream->GetFpsRate());
        resp->put_U32(stream->GetHeight());
        resp->put_U32(stream->GetWidth());
        resp->put_S64(stream->GetAspect() * 10000.0);
        break;

      case cStreamInfo::scSUBTITLE:
        resp->put_String(stream->TypeName());
        resp->put_String(stream->GetLanguage());
        resp->put_U32(stream->CompositionPageId());
        resp->put_U32(stream->AncillaryPageId());
        break;

      case cStreamInfo::scTELETEXT:
        resp->put_String(stream->TypeName());
        break;

      default:
        break;
    }
  }

  m_FilterMutex.Unlock();

  m_Queue->Add(resp);
  m_requestStreamChange = false;
}
Exemplo n.º 10
0
Packet* Demux::Read()
{
  if(ConnectionLost() || Aborting()) {
    return NULL;
  }

  Packet* p = NULL;
  MsgPacket* pkt = NULL;
  m_lock.Lock();

  if(m_queuelocked) {
      m_lock.Unlock();
      return m_client->AllocatePacket(0);
  }

  if (m_buffer != NULL) {
    pkt = m_buffer->get();

    if (pkt == NULL) {
      m_lock.Unlock();
      m_cond.Wait(100);
      m_lock.Lock();
      pkt = m_buffer->get();
    }

    if (pkt != NULL) {
      pkt->rewind();

      switch (pkt->getMsgID()) {
      case XVDR_STREAM_MUXPKT: {
        uint16_t id = pkt->get_U16();
        int64_t pts = pkt->get_S64();
        int64_t dts = pkt->get_S64();
        uint32_t duration = pkt->get_U32();
        uint32_t length = pkt->get_U32();
        uint8_t* payload = pkt->consume(length);
        Stream& stream = m_streams[id];

        if (stream.PhysicalId != id) {
          m_client->Log(DEBUG, "stream id %i not found", id);
        } else {
          p = m_client->AllocatePacket(length);
          m_client->SetPacketData(p, payload, stream.Index, dts, pts, duration);
        }
        break;
      }
      case XVDR_STREAM_CHANGE: {
        StreamChange(pkt);
        p = m_client->StreamChange(m_streams);
        break;
      }
      }
    }

    if (p == NULL) {
      p = m_client->AllocatePacket(0);
    }

    m_buffer->release(pkt);

    m_lock.Unlock();
    return p;
  }

  bool bEmpty = m_queue.empty();

  // empty queue -> wait for packet
  if (bEmpty) {
         m_lock.Unlock();

         // request packets in timeshift mode
         if(m_timeshiftmode)
         {
           MsgPacket req(XVDR_CHANNELSTREAM_REQUEST, XVDR_CHANNEL_STREAM);
           if(!Session::TransmitMessage(&req))
             return NULL;
         }

         m_cond.Wait(100);

         m_lock.Lock();
         bEmpty = m_queue.empty();
  }

  if (!bEmpty)
  {
    p = m_queue.front();
    m_queue.pop();
  }

  m_lock.Unlock();

  if(p == NULL) {
    p = m_client->AllocatePacket(0);
  }

  return p;
}
Exemplo n.º 11
0
void cLiveStreamer::RequestSignalInfo()
{
  // do not send (and pollute the client with) signal information
  // if we are paused
  if(IsPaused())
    return;

  MsgPacket* resp = new MsgPacket(XVDR_STREAM_SIGNALINFO, XVDR_CHANNEL_STREAM);

  int DeviceNumber = m_Device->DeviceNumber() + 1;
  int Strength = 0;
  int Quality = 0;

  if(!TimeShiftMode()) {
    Strength = m_Device->SignalStrength();
    Quality = m_Device->SignalQuality();
  }

  resp->put_String(*cString::sprintf("%s #%d - %s", 
#if VDRVERSNUM < 10728
#warning "VDR versions < 1.7.28 do not support all features"
			"Unknown",
			DeviceNumber,
			"Unknown"));
#else
			(const char*)m_Device->DeviceType(),
			DeviceNumber,
			(const char*)m_Device->DeviceName()));
#endif

  // Quality:
  // 4 - NO LOCK
  // 3 - NO SYNC
  // 2 - NO VITERBI
  // 1 - NO CARRIER
  // 0 - NO SIGNAL

  if(TimeShiftMode())
  {
    resp->put_String("TIMESHIFT");
  }
  else if(Quality == -1)
  {
    resp->put_String("UNKNOWN (Incompatible device)");
    Quality = 0;
  }
  else
    resp->put_String(*cString::sprintf("%s:%s:%s:%s:%s", 
			(Quality > 4) ? "LOCKED" : "-",
			(Quality > 0) ? "SIGNAL" : "-",
			(Quality > 1) ? "CARRIER" : "-",
			(Quality > 2) ? "VITERBI" : "-",
			(Quality > 3) ? "SYNC" : "-"));

  resp->put_U32((Strength << 16 ) / 100);
  resp->put_U32((Quality << 16 ) / 100);
  resp->put_U32(0);
  resp->put_U32(0);

  DEBUGLOG("RequestSignalInfo");
  m_Queue->Add(resp);
}