From d375f3ea3ead88dcc4f41c6e5c551370cd305755 Mon Sep 17 00:00:00 2001 From: Felix Domke Date: Sun, 14 Aug 2005 16:25:44 +0000 Subject: [PATCH] - add tstools to evaluate PTS values from TS files for playback --- lib/dvb/tstools.cpp | 151 ++++++++++++++++++++++++++++++++++++++++++++ lib/dvb/tstools.h | 42 ++++++++++++ 2 files changed, 193 insertions(+) create mode 100644 lib/dvb/tstools.cpp create mode 100644 lib/dvb/tstools.h diff --git a/lib/dvb/tstools.cpp b/lib/dvb/tstools.cpp new file mode 100644 index 00000000..5d1c7e35 --- /dev/null +++ b/lib/dvb/tstools.cpp @@ -0,0 +1,151 @@ +#include +#include +#include + +#include + +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; +} + diff --git a/lib/dvb/tstools.h b/lib/dvb/tstools.h new file mode 100644 index 00000000..c6f2cbbc --- /dev/null +++ b/lib/dvb/tstools.h @@ -0,0 +1,42 @@ +#ifndef __lib_dvb_tstools_h +#define __lib_dvb_tstools_h + +#include + +/* + * 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 -- 2.30.2