add movemode in channellist (later it should only useable in bouquets)
[enigma2.git] / lib / dvb / tstools.cpp
1 #include <lib/dvb/tstools.h>
2 #include <unistd.h>
3 #include <fcntl.h>
4
5 #include <stdio.h>
6
7 eDVBTSTools::eDVBTSTools()
8 {
9         m_fd = -1;
10         m_pid = -1;
11         m_maxrange = 1*1024*1024;
12         
13         m_begin_valid = 0;
14         m_end_valid = 0;
15 }
16
17 eDVBTSTools::~eDVBTSTools()
18 {
19         closeFile();
20 }
21
22 int eDVBTSTools::openFile(const char *filename)
23 {
24         closeFile();
25         m_fd = ::open(filename, O_RDONLY);
26         if (m_fd < 0)
27                 return -1;
28         return 0;
29 }
30
31 void eDVBTSTools::closeFile()
32 {
33         if (m_fd >= 0)
34                 ::close(m_fd);
35 }
36
37 void eDVBTSTools::setSyncPID(int pid)
38 {
39         m_pid = pid;
40 }
41
42 void eDVBTSTools::setSearchRange(int maxrange)
43 {
44         m_maxrange = maxrange;
45 }
46
47 int eDVBTSTools::getPTS(off_t &offset, pts_t &pts)
48 {
49         if (m_fd < 0)
50                 return -1;
51
52         offset -= offset % 188;
53         
54                 // TODO: multiple files!        
55         if (lseek(m_fd, offset, SEEK_SET) < 0)
56                 return -1;
57
58         int left = m_maxrange;
59         
60         while (left >= 188)
61         {
62                 unsigned char block[188];
63                 if (read(m_fd, block, 188) != 188)
64                         break;
65                 left -= 188;
66                 offset += 188;
67                 
68                 if (block[0] != 0x47)
69                 {
70                         int i = 0;
71                         while (i < 188)
72                                 if (block[i] == 0x47)
73                                         break;
74                         offset = lseek(m_fd, i - 188, SEEK_CUR);
75                         continue;
76                 }
77                 
78                 int pid = ((block[1] << 8) | block[2]) & 0x1FFF;
79                 int pusi = !!(block[1] & 0x40);
80                 
81 //              printf("PID %04x, PUSI %d\n", pid, pusi);
82                 
83                 if (m_pid >= 0)
84                         if (pid != m_pid)
85                                 continue;
86                 if (!pusi)
87                         continue;
88                 
89                         /* ok, now we have a PES header */
90                 unsigned char *pes;
91                 
92                         /* check for adaption field */
93                 if (block[3] & 0x10)
94                         pes = block + block[4] + 4 + 1;
95                 else
96                         pes = block + 4;
97                 
98                         /* somehow not a startcode. (this is invalid, since pusi was set.) ignore it. */
99                 if (pes[0] || pes[1] || (pes[2] != 1))
100                         continue;
101                 
102                 if (pes[7] & 0x80) /* PTS */
103                 {
104                         pts  = ((unsigned long long)(pes[ 9]&0xE))  << 29;
105                         pts |= ((unsigned long long)(pes[10]&0xFF)) << 22;
106                         pts |= ((unsigned long long)(pes[11]&0xFE)) << 14;
107                         pts |= ((unsigned long long)(pes[12]&0xFF)) << 7;
108                         pts |= ((unsigned long long)(pes[13]&0xFE)) >> 1;
109                         offset -= 188;
110                         return 0;
111                 }
112         }
113
114         return -1;
115 }
116
117 void eDVBTSTools::calcBegin()
118 {
119         if (m_fd < 0)   
120                 return;
121         if (!m_begin_valid)
122         {
123                 m_offset_begin = 0;
124                 if (!getPTS(m_offset_begin, m_pts_begin))
125                         m_begin_valid = 1;
126         }
127 }
128
129 void eDVBTSTools::calcEnd()
130 {
131         if (m_fd < 0)   
132                 return;
133         
134         if (!m_end_valid)
135         {
136                 m_offset_end = lseek(m_fd, 0, SEEK_END) - m_maxrange;
137                 if (!getPTS(m_offset_end, m_pts_end))
138                         m_end_valid = 1;
139         }
140 }
141
142 int eDVBTSTools::calcLen(pts_t &len)
143 {
144         calcBegin(); calcEnd();
145         if (!(m_begin_valid && m_end_valid))
146                 return -1;
147         len = m_pts_end - m_pts_begin;
148         return 0;
149 }
150