summaryrefslogtreecommitdiff
path: root/remux/ts2es.c
diff options
context:
space:
mode:
authorFrank Schmirler <schmirl@puter.linogate.de>2010-12-02 08:53:01 +0100
committerFrank Schmirler <schmirl@puter.linogate.de>2010-12-02 08:53:01 +0100
commit5e30711bfdb28085234a5ef6da4f4e44305ac3e4 (patch)
treed15809d23eeeed7fda55d9450b1af7c99d6eb5d6 /remux/ts2es.c
downloadvdr-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.c140
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;
+}
+