fix linked tuners (i hope)
[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                                 if (block[i] == 0x47)
75                                         break;
76                         offset = lseek(m_fd, i - 188, SEEK_CUR);
77                         continue;
78                 }
79                 
80                 int pid = ((block[1] << 8) | block[2]) & 0x1FFF;
81                 int pusi = !!(block[1] & 0x40);
82                 
83 //              printf("PID %04x, PUSI %d\n", pid, pusi);
84                 
85                 if (m_pid >= 0)
86                         if (pid != m_pid)
87                                 continue;
88                 if (!pusi)
89                         continue;
90                 
91                         /* ok, now we have a PES header */
92                 unsigned char *pes;
93                 
94                         /* check for adaption field */
95                 if (block[3] & 0x20)
96                         pes = block + block[4] + 4 + 1;
97                 else
98                         pes = block + 4;
99                 
100                         /* somehow not a startcode. (this is invalid, since pusi was set.) ignore it. */
101                 if (pes[0] || pes[1] || (pes[2] != 1))
102                         continue;
103                 
104                 if (pes[7] & 0x80) /* PTS */
105                 {
106                         pts  = ((unsigned long long)(pes[ 9]&0xE))  << 29;
107                         pts |= ((unsigned long long)(pes[10]&0xFF)) << 22;
108                         pts |= ((unsigned long long)(pes[11]&0xFE)) << 14;
109                         pts |= ((unsigned long long)(pes[12]&0xFF)) << 7;
110                         pts |= ((unsigned long long)(pes[13]&0xFE)) >> 1;
111                         offset -= 188;
112                         return 0;
113                 }
114         }
115         
116         return -1;
117 }
118
119 void eDVBTSTools::calcBegin()
120 {
121         if (m_fd < 0)   
122                 return;
123         if (!m_begin_valid)
124         {
125                 m_offset_begin = 0;
126                 if (!getPTS(m_offset_begin, m_pts_begin))
127                         m_begin_valid = 1;
128         }
129 }
130
131 void eDVBTSTools::calcEnd()
132 {
133         if (m_fd < 0)   
134                 return;
135         
136         m_offset_end = lseek(m_fd, 0, SEEK_END);
137         
138         int maxiter = 10;
139         
140         while (!m_end_valid)
141         {
142                 if (!--maxiter)
143                         return;
144                 
145                 m_offset_end -= m_maxrange;
146                 if (m_offset_end < 0)
147                         m_offset_end = 0;
148                 if (!getPTS(m_offset_end, m_pts_end))
149                         m_end_valid = 1;
150                 if (!m_offset_end)
151                         return;
152         }
153 }
154
155 int eDVBTSTools::calcLen(pts_t &len)
156 {
157         calcBegin(); calcEnd();
158         if (!(m_begin_valid && m_end_valid))
159                 return -1;
160         len = m_pts_end - m_pts_begin;
161         return 0;
162 }
163
164 int eDVBTSTools::calcBitrate()
165 {
166         calcBegin(); calcEnd();
167         if (!(m_begin_valid && m_end_valid))
168                 return -1;
169
170         pts_t len_in_pts = m_pts_end - m_pts_begin;
171         off_t len_in_bytes = m_offset_end - m_offset_begin;
172         
173         if (!len_in_pts)
174                 return -1;
175         
176         unsigned long long bitrate = len_in_bytes * 90000 * 8 / len_in_pts;
177         if ((bitrate < 10000) || (bitrate > 100000000))
178                 return -1;
179         
180         return bitrate;
181 }