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