diff options
author | Frank Schmirler <schmirl@puter.linogate.de> | 2010-12-02 08:53:01 +0100 |
---|---|---|
committer | Frank Schmirler <schmirl@puter.linogate.de> | 2010-12-02 08:53:01 +0100 |
commit | 5e30711bfdb28085234a5ef6da4f4e44305ac3e4 (patch) | |
tree | d15809d23eeeed7fda55d9450b1af7c99d6eb5d6 /client/filter.c | |
download | vdr-plugin-streamdev-5e30711bfdb28085234a5ef6da4f4e44305ac3e4.tar.gz vdr-plugin-streamdev-5e30711bfdb28085234a5ef6da4f4e44305ac3e4.tar.bz2 |
Snapshot 2007-03-20
Diffstat (limited to 'client/filter.c')
-rw-r--r-- | client/filter.c | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/client/filter.c b/client/filter.c new file mode 100644 index 0000000..daf534a --- /dev/null +++ b/client/filter.c @@ -0,0 +1,119 @@ +/* + * $Id: filter.c,v 1.3 2005/11/06 16:43:58 lordjaxom Exp $ + */ + +#include "client/filter.h" +#include "client/socket.h" +#include "tools/select.h" +#include "common.h" + +#include <vdr/ringbuffer.h> +#include <vdr/device.h> + +#if VDRVERSNUM >= 10300 + +cStreamdevFilter::cStreamdevFilter(u_short Pid, u_char Tid, u_char Mask) { + m_Used = 0; + m_Pid = Pid; + m_Tid = Tid; + m_Mask = Mask; + + if (pipe(m_Pipe) != 0 || fcntl(m_Pipe[0], F_SETFL, O_NONBLOCK) != 0) { + esyslog("streamev-client: coudln't open section filter pipe: %m"); + m_Pipe[0] = m_Pipe[1] = -1; + } +} + +cStreamdevFilter::~cStreamdevFilter() { + Dprintf("~cStreamdevFilter %p\n", this); + if (m_Pipe[0] >= 0) + close(m_Pipe[0]); + if (m_Pipe[1] >= 0) + close(m_Pipe[1]); +} + +bool cStreamdevFilter::PutSection(const uchar *Data, int Length) { + if (m_Used + Length >= (int)sizeof(m_Buffer)) { + esyslog("ERROR: Streamdev: Section handler buffer overflow (%d bytes lost)", + Length); + m_Used = 0; + return true; + } + memcpy(m_Buffer + m_Used, Data, Length); + m_Used += Length; + + if (m_Used > 3) { + int length = (((m_Buffer[1] & 0x0F) << 8) | m_Buffer[2]) + 3; + if (m_Used == length) { + if (write(m_Pipe[1], m_Buffer, length) < 0) + return false; + m_Used = 0; + } + } + return true; +} + +cStreamdevFilters::cStreamdevFilters(void): + cThread("streamdev-client: sections assembler") { + m_Active = false; + m_RingBuffer = new cRingBufferLinear(MEGABYTE(1), TS_SIZE * 2, true); + Start(); +} + +cStreamdevFilters::~cStreamdevFilters() { + if (m_Active) { + m_Active = false; + Cancel(3); + } + delete m_RingBuffer; +} + +int cStreamdevFilters::OpenFilter(u_short Pid, u_char Tid, u_char Mask) { + cStreamdevFilter *f = new cStreamdevFilter(Pid, Tid, Mask); + Add(f); + return f->ReadPipe(); +} + +cStreamdevFilter *cStreamdevFilters::Matches(u_short Pid, u_char Tid) { + for (cStreamdevFilter *f = First(); f; f = Next(f)) { + if (f->Matches(Pid, Tid)) + return f; + } + return NULL; +} + +void cStreamdevFilters::Put(const uchar *Data) { + int p = m_RingBuffer->Put(Data, TS_SIZE); + if (p != TS_SIZE) + m_RingBuffer->ReportOverflow(TS_SIZE - p); +} + +void cStreamdevFilters::Action(void) { + m_Active = true; + while (m_Active) { + int recvd; + const uchar *block = m_RingBuffer->Get(recvd); + + if (block && recvd > 0) { + cStreamdevFilter *f; + u_short pid = (((u_short)block[1] & PID_MASK_HI) << 8) | block[2]; + u_char tid = block[3]; + + if ((f = Matches(pid, tid)) != NULL) { + int len = block[4]; + if (!f->PutSection(block + 5, len)) { + if (errno != EPIPE) { + esyslog("streamdev-client: couldn't send section packet: %m"); + Dprintf("FATAL ERROR: %m\n"); + } + ClientSocket.SetFilter(f->Pid(), f->Tid(), f->Mask(), false); + Del(f); + } + } + m_RingBuffer->Del(TS_SIZE); + } else + usleep(1); + } +} + +#endif // VDRVERSNUM >= 10300 |