1 #include <lib/dvb/tstools.h>
2 #include <lib/base/eerror.h>
8 eDVBTSTools::eDVBTSTools()
11 m_maxrange = 256*1024;
19 eDVBTSTools::~eDVBTSTools()
24 int eDVBTSTools::openFile(const char *filename)
28 m_streaminfo.load((std::string(filename) + ".ap").c_str());
30 if (!m_streaminfo.empty())
34 eDebug("no recorded stream information available");
38 if (m_file.open(filename) < 0)
43 void eDVBTSTools::closeFile()
48 void eDVBTSTools::setSyncPID(int pid)
53 void eDVBTSTools::setSearchRange(int maxrange)
55 m_maxrange = maxrange;
58 /* getPTS extracts a pts value from any PID at a given offset. */
59 int eDVBTSTools::getPTS(off_t &offset, pts_t &pts, int fixed)
62 return m_streaminfo.getPTS(offset, pts);
64 if (!m_file.valid() < 0)
67 offset -= offset % 188;
69 if (m_file.lseek(offset, SEEK_SET) < 0)
72 int left = m_maxrange;
76 unsigned char block[188];
77 if (m_file.read(block, 188) != 188)
94 offset = m_file.lseek(i - 188, SEEK_CUR);
98 int pid = ((block[1] << 8) | block[2]) & 0x1FFF;
99 int pusi = !!(block[1] & 0x40);
101 // printf("PID %04x, PUSI %d\n", pid, pusi);
109 /* ok, now we have a PES header */
112 /* check for adaption field */
114 pes = block + block[4] + 4 + 1;
118 /* somehow not a startcode. (this is invalid, since pusi was set.) ignore it. */
119 if (pes[0] || pes[1] || (pes[2] != 1))
122 if (pes[7] & 0x80) /* PTS */
124 pts = ((unsigned long long)(pes[ 9]&0xE)) << 29;
125 pts |= ((unsigned long long)(pes[10]&0xFF)) << 22;
126 pts |= ((unsigned long long)(pes[11]&0xFE)) << 14;
127 pts |= ((unsigned long long)(pes[12]&0xFF)) << 7;
128 pts |= ((unsigned long long)(pes[13]&0xFE)) >> 1;
131 /* convert to zero-based */
133 fixupPTS(offset, pts);
141 int eDVBTSTools::fixupPTS(const off_t &offset, pts_t &now)
143 if (m_use_streaminfo)
145 return m_streaminfo.fixupPTS(offset, now);
148 /* for the simple case, we assume one epoch, with up to one wrap around in the middle. */
152 eDebug("begin not valid, can't fixup");
156 pts_t pos = m_pts_begin;
157 if ((now < pos) && ((pos - now) < 90000 * 10))
163 if (now < pos) /* wrap around */
164 now = now + 0x200000000LL - pos;
171 int eDVBTSTools::getOffset(off_t &offset, pts_t &pts)
173 if (m_use_streaminfo)
175 offset = m_streaminfo.getAccessPoint(pts);
179 int bitrate = calcBitrate(); /* in bits/s */
183 offset = (pts * (pts_t)bitrate) / 8ULL / 90000ULL;
184 offset -= offset % 188;
190 int eDVBTSTools::getNextAccessPoint(pts_t &ts, const pts_t &start, int direction)
192 if (m_use_streaminfo)
193 return m_streaminfo.getNextAccessPoint(ts, start, direction);
196 eDebug("can't get next access point without streaminfo");
201 void eDVBTSTools::calcBegin()
209 if (!getPTS(m_offset_begin, m_pts_begin))
214 void eDVBTSTools::calcEnd()
219 off_t end = m_file.lseek(0, SEEK_END);
221 if (abs(end - m_offset_end) > 1*1024*1024)
225 eDebug("file size changed, recalc length");
235 m_offset_end -= m_maxrange;
236 if (m_offset_end < 0)
238 if (!getPTS(m_offset_end, m_pts_end))
245 int eDVBTSTools::calcLen(pts_t &len)
247 calcBegin(); calcEnd();
248 if (!(m_begin_valid && m_end_valid))
250 len = m_pts_end - m_pts_begin;
253 len += 0x200000000LL;
257 int eDVBTSTools::calcBitrate()
259 calcBegin(); calcEnd();
260 if (!(m_begin_valid && m_end_valid))
263 pts_t len_in_pts = m_pts_end - m_pts_begin;
267 len_in_pts += 0x200000000LL;
268 off_t len_in_bytes = m_offset_end - m_offset_begin;
273 unsigned long long bitrate = len_in_bytes * 90000 * 8 / len_in_pts;
274 if ((bitrate < 10000) || (bitrate > 100000000))