bool cBackgroundWriterI::Flush(int TimeoutMs) { uint64_t WaitEnd = cTimeMs::Now(); // wait for ring buffer to drain if (TimeoutMs > 0) { WaitEnd += (uint64_t)TimeoutMs; while (cTimeMs::Now() < WaitEnd && Running() && m_RingBuffer.Available() > 0) cCondWait::SleepMs(3); } int Available = m_RingBuffer.Available(); if (m_IsSocket && Available <= 0) { // flush corked data too Cork(); } return Available <= 0; }
void CPulseAEStream::Resume() { if (m_Initialized) m_Paused = Cork(false); }
void CPulseAEStream::Pause() { if (m_Initialized) m_Paused = Cork(true); }
void cTcpWriter::Action(void) { uint64_t NextHeaderPos = 0; uint64_t GetPos = 0; cPoller Poller (m_fd, true); bool CorkReq = false; while (Running()) { if (!Poller.Poll(100)) continue; if (CorkReq && m_RingBuffer.Available() <= 0) { // Force TCP packet to avoid delaying control messages Cork(); CorkReq = false; } uint64_t StartPos; int Count = 0; int n; uchar *Data = m_RingBuffer.Get(Count); if (!Data || Count <= 0) continue; Lock(); // uint64_t m_DiscardStart can not be read atomically (IA32) StartPos = m_DiscardEnd; Unlock(); // Next frame ? if (NextHeaderPos == GetPos) { // Discard data ? if (StartPos > GetPos) { // we're at frame boundary // drop only data packets, not control messages stream_tcp_header_t *header = (stream_tcp_header_t*)Data; if (eStreamId(header->stream) == sidVdr) { Count = min(Count, (int)(StartPos - GetPos)); // size of next (complete) packet. // drop only one packet at time. int pkt_len = ntohl(header->len) + sizeof(stream_tcp_header_t); if (Count >= pkt_len) { // drop only complete packets. // some packets are not dropped (packets overlapping end of ringbuffer) Count = pkt_len; m_RingBuffer.Del(Count); GetPos += Count; NextHeaderPos = GetPos; CorkReq = true; // force sending last frame continue; } } } // Next frame if (Count < (int)sizeof(stream_tcp_header_t)) LOGMSG("cBackgroundWriter @NextHeaderPos: Count < header size !"); // limit single write to size of next (complete) packet. // (we need to track packet boundaries) stream_tcp_header_t *header = (stream_tcp_header_t*)Data; int pkt_len = ntohl(header->len) + sizeof(stream_tcp_header_t); if (Count > pkt_len) Count = pkt_len; // next packet start position in stream NextHeaderPos = GetPos + pkt_len; // check for control message if (eStreamId(header->stream) == sidControl) CorkReq = true; } else { // end of prev frame Count = min(Count, (int)(NextHeaderPos-GetPos)); } errno = 0; n = write(m_fd, Data, Count); if (n <= 0) { if (n == 0) { LOGERR("cBackgroundWriter: Client disconnected data stream ?"); break; } if (errno == EINTR || errno == EWOULDBLOCK) continue; LOGERR("cBackgroundWriter: TCP write error"); break; } GetPos += n; m_RingBuffer.Del(n); } m_RingBuffer.Clear(); }