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 /remux/ts2es.c | |
download | vdr-plugin-streamdev-5e30711bfdb28085234a5ef6da4f4e44305ac3e4.tar.gz vdr-plugin-streamdev-5e30711bfdb28085234a5ef6da4f4e44305ac3e4.tar.bz2 |
Snapshot 2007-03-20
Diffstat (limited to 'remux/ts2es.c')
-rw-r--r-- | remux/ts2es.c | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/remux/ts2es.c b/remux/ts2es.c new file mode 100644 index 0000000..3476e24 --- /dev/null +++ b/remux/ts2es.c @@ -0,0 +1,140 @@ +#include "remux/ts2es.h" +#include "server/streamer.h" +#include "libdvbmpeg/transform.h" +#include "common.h" +#include <vdr/device.h> + +// from VDR's remux.c +#define MAXNONUSEFULDATA (10*1024*1024) + +class cTS2ES: public ipack { + friend void PutES(uint8_t *Buffer, int Size, void *Data); + +private: + cRingBufferLinear *m_ResultBuffer; + +public: + cTS2ES(cRingBufferLinear *ResultBuffer); + ~cTS2ES(); + + void PutTSPacket(const uint8_t *Buffer); +}; + +void PutES(uint8_t *Buffer, int Size, void *Data) +{ + cTS2ES *This = (cTS2ES*)Data; + uint8_t payl = Buffer[8] + 9 + This->start - 1; + int count = Size - payl; + + int n = This->m_ResultBuffer->Put(Buffer + payl, count); + if (n != count) + esyslog("ERROR: result buffer overflow, dropped %d out of %d byte", count - n, count); + This->start = 1; +} + +cTS2ES::cTS2ES(cRingBufferLinear *ResultBuffer) +{ + m_ResultBuffer = ResultBuffer; + + init_ipack(this, IPACKS, PutES, 0); + data = (void*)this; +} + +cTS2ES::~cTS2ES() +{ + free_ipack(this); +} + +void cTS2ES::PutTSPacket(const uint8_t *Buffer) { + if (!Buffer) + return; + + if (Buffer[1] & 0x80) { // ts error + // TODO + } + + if (Buffer[1] & 0x40) { // payload start + if (plength == MMAX_PLENGTH - 6) { + plength = found - 6; + found = 0; + send_ipack(this); + reset_ipack(this); + } + } + + uint8_t off = 0; + + if (Buffer[3] & 0x20) { // adaptation field? + off = Buffer[4] + 1; + if (off + 4 > TS_SIZE - 1) + return; + } + + instant_repack((uint8_t*)(Buffer + 4 + off), TS_SIZE - 4 - off, this); +} + +cTS2ESRemux::cTS2ESRemux(int Pid): + m_Pid(Pid), + m_ResultBuffer(new cRingBufferLinear(WRITERBUFSIZE, IPACKS)), + m_Remux(new cTS2ES(m_ResultBuffer)) +{ + m_ResultBuffer->SetTimeouts(0, 100); +} + +cTS2ESRemux::~cTS2ESRemux() +{ + delete m_Remux; + delete m_ResultBuffer; +} + +int cTS2ESRemux::Put(const uchar *Data, int Count) +{ + int used = 0; + + // Make sure we are looking at a TS packet: + + while (Count > TS_SIZE) { + if (Data[0] == TS_SYNC_BYTE && Data[TS_SIZE] == TS_SYNC_BYTE) + break; + Data++; + Count--; + used++; + } + + if (used) + esyslog("ERROR: skipped %d byte to sync on TS packet", used); + + // Convert incoming TS data into ES: + + for (int i = 0; i < Count; i += TS_SIZE) { + if (Count - i < TS_SIZE) + break; + if (Data[i] != TS_SYNC_BYTE) + break; + if (m_ResultBuffer->Free() < 2 * IPACKS) + break; // A cTS2ES might write one full packet and also a small rest + int pid = cTSRemux::GetPid(Data + i + 1); + if (Data[i + 3] & 0x10) { // got payload + if (m_Pid == pid) + m_Remux->PutTSPacket(Data + i); + } + used += TS_SIZE; + } + +/* + // Check if we're getting anywhere here: + if (!synced && skipped >= 0) { + if (skipped > MAXNONUSEFULDATA) { + esyslog("ERROR: no useful data seen within %d byte of video stream", skipped); + skipped = -1; + if (exitOnFailure) + cThread::EmergencyExit(true); + } + else + skipped += used; + } +*/ + + return used; +} + |