--- /dev/null
+#include <lib/dvb/tstools.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <stdio.h>
+
+eDVBTSTools::eDVBTSTools()
+{
+ m_fd = -1;
+ m_pid = -1;
+ m_maxrange = 1*1024*1024;
+
+ m_begin_valid = 0;
+ m_end_valid = 0;
+}
+
+eDVBTSTools::~eDVBTSTools()
+{
+ closeFile();
+}
+
+int eDVBTSTools::openFile(const char *filename)
+{
+ closeFile();
+ m_fd = ::open(filename, O_RDONLY);
+ if (m_fd < 0)
+ return -1;
+ return 0;
+}
+
+void eDVBTSTools::closeFile()
+{
+ if (m_fd >= 0)
+ ::close(m_fd);
+}
+
+void eDVBTSTools::setSyncPID(int pid)
+{
+ m_pid = pid;
+}
+
+void eDVBTSTools::setSearchRange(int maxrange)
+{
+ m_maxrange = maxrange;
+}
+
+int eDVBTSTools::getPTS(off_t &offset, pts_t &pts)
+{
+ if (m_fd < 0)
+ return -1;
+ if (m_pid < 0)
+ return -1;
+
+ offset -= offset % 188;
+
+ // TODO: multiple files!
+ if (lseek(m_fd, offset, SEEK_SET) < 0)
+ return -1;
+
+ int left = m_maxrange;
+
+ while (left >= 188)
+ {
+ unsigned char block[188];
+ if (read(m_fd, block, 188) != 188)
+ break;
+ left -= 188;
+ offset += 188;
+
+ if (block[0] != 0x47)
+ {
+ int i = 0;
+ while (i < 188)
+ if (block[i] == 0x47)
+ break;
+ offset = lseek(m_fd, i - 188, SEEK_CUR);
+ continue;
+ }
+
+ int pid = ((block[1] << 8) | block[2]) & 0x1FFF;
+ int pusi = !!(block[1] & 0x40);
+
+// printf("PID %04x, PUSI %d\n", pid, pusi);
+
+ if (pid != m_pid)
+ continue;
+ if (!pusi)
+ continue;
+
+ /* ok, now we have a PES header */
+ unsigned char *pes;
+
+ /* check for adaption field */
+ if (block[3] & 0x10)
+ pes = block + block[4] + 4 + 1;
+ else
+ pes = block + 4;
+
+ /* somehow not a startcode. (this is invalid, since pusi was set.) ignore it. */
+ if (pes[0] || pes[1] || (pes[2] != 1))
+ continue;
+
+ if (pes[7] & 0x80) /* PTS */
+ {
+ pts = ((unsigned long long)(pes[ 9]&0xE)) << 29;
+ pts |= ((unsigned long long)(pes[10]&0xFF)) << 22;
+ pts |= ((unsigned long long)(pes[11]&0xFE)) << 14;
+ pts |= ((unsigned long long)(pes[12]&0xFF)) << 7;
+ pts |= ((unsigned long long)(pes[13]&0xFE)) >> 1;
+ offset -= 188;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+void eDVBTSTools::calcBegin()
+{
+ if (m_fd < 0)
+ return;
+ if (!m_begin_valid)
+ {
+ m_offset_begin = 0;
+ if (!getPTS(m_offset_begin, m_pts_begin))
+ m_begin_valid = 1;
+ }
+}
+
+void eDVBTSTools::calcEnd()
+{
+ if (m_fd < 0)
+ return;
+
+ if (!m_end_valid)
+ {
+ m_offset_end = lseek(m_fd, 0, SEEK_END) - m_maxrange;
+ if (!getPTS(m_offset_end, m_pts_end))
+ m_end_valid = 1;
+ }
+}
+
+int eDVBTSTools::calcLen(pts_t &len)
+{
+ calcBegin(); calcEnd();
+ if (!(m_begin_valid && m_end_valid))
+ return -1;
+ len = m_pts_end - m_pts_begin;
+ return 0;
+}
+
--- /dev/null
+#ifndef __lib_dvb_tstools_h
+#define __lib_dvb_tstools_h
+
+#include <sys/types.h>
+
+/*
+ * Note: we're interested in PTS values, not STC values.
+ * thus we're not evaluating PES headers, not adaption fields.
+ */
+
+class eDVBTSTools
+{
+public:
+ typedef unsigned long long pts_t;
+ eDVBTSTools();
+ ~eDVBTSTools();
+
+ int openFile(const char *filename);
+ void closeFile();
+
+ void setSyncPID(int pid);
+ void setSearchRange(int maxrange);
+
+ /* get first PTS *after* the given offset. */
+ int getPTS(off_t &offset, pts_t &pts);
+
+ void calcBegin();
+ void calcEnd();
+
+ int calcLen(pts_t &len);
+
+private:
+ int m_fd, m_pid;
+ int m_maxrange;
+
+ int m_begin_valid, m_end_valid;
+ pts_t m_pts_begin, m_pts_end;
+ off_t m_offset_begin, m_offset_end;
+};
+
+
+#endif