TranscodingSetup : fix misspelling name.
[vuplus_dvbapp] / lib / dvb / esection.h
1 #ifndef __esection_h
2 #define __esection_h
3
4 #include <lib/dvb/idemux.h>
5 #include <set>
6
7 #define TABLE_eDebug(x...) do { if (m_debug) eDebug(x); } while(0)
8 #define TABLE_eDebugNoNewLine(x...) do { if (m_debug) eDebugNoNewLine(x); } while(0)
9
10 class eGTable: public iObject, public Object
11 {
12         DECLARE_REF(eGTable);
13         ePtr<iDVBSectionReader> m_reader;
14         eDVBTableSpec m_table;
15         
16         unsigned int m_tries;
17         
18         ePtr<eTimer> m_timeout;
19
20         void sectionRead(const __u8 *data);
21         void timeout();
22         ePtr<eConnection> m_sectionRead_conn;
23 protected:
24         bool m_debug;
25         virtual int createTable(unsigned int nr, const __u8 *data, unsigned int max)=0;
26 public:
27         Signal1<void, int> tableReady;
28         eGTable(bool debug=true);
29         RESULT start(iDVBSectionReader *reader, const eDVBTableSpec &table);
30         RESULT start(iDVBDemux *reader, const eDVBTableSpec &table);
31         RESULT getSpec(eDVBTableSpec &spec) { spec = m_table; return 0; }
32         virtual ~eGTable();
33         int error;
34         int ready;
35 };
36
37 template <class Section>
38 class eTable: public eGTable
39 {
40 private:
41         std::vector<Section*> sections;
42         std::set<int> avail;
43         unsigned char m_section_data[4096];
44 protected:
45         int createTable(unsigned int nr, const __u8 *data, unsigned int max)
46         {
47                 unsigned int ssize = sections.size();
48                 if (max < ssize || nr >= max)
49                 {
50                         TABLE_eDebug("kaputt max(%d) < ssize(%d) || nr(%d) >= max(%d)",
51                                 max, ssize, nr, max);
52                         return 0;
53                 }
54                 if (avail.find(nr) != avail.end())
55                         delete sections[nr];
56
57                 memset(m_section_data, 0, 4096);
58                 memcpy(m_section_data, data, 4096);
59
60                 sections.resize(max);
61                 sections[nr] = new Section(data);
62                 avail.insert(nr);
63
64                 for (unsigned int i = 0; i < max; ++i)
65                         if (avail.find(i) != avail.end())
66                                 TABLE_eDebugNoNewLine("+");
67                         else
68                                 TABLE_eDebugNoNewLine("-");
69                                 
70                 TABLE_eDebug(" %zd/%d TID %02x", avail.size(), max, data[0]);
71
72                 if (avail.size() == max)
73                 {
74                         TABLE_eDebug("done!");
75                         return 1;
76                 } else
77                         return 0;
78         }
79 public:
80         std::vector<Section*> &getSections() { return sections; }
81         unsigned char* getBufferData() { return m_section_data; }
82         eTable(bool debug=true): eGTable(debug)
83         {
84         }
85         ~eTable()
86         {
87                 for (std::set<int>::iterator i(avail.begin()); i != avail.end(); ++i)
88                         delete sections[*i];
89         }
90 };
91
92 class eAUGTable: public Object
93 {
94 protected:
95         void slotTableReady(int);
96 public:
97         Signal1<void, int> tableReady;
98         virtual void getNext(int err)=0;
99 };
100
101 template <class Table>
102 class eAUTable: public eAUGTable
103 {
104         ePtr<Table> current, next;              // current is READY AND ERRORFREE, next is not yet ready
105         int first;
106         ePtr<iDVBDemux> m_demux;
107         eMainloop *ml;
108
109         /* needed to detect broken table version handling (seen on some m2ts files) */
110         struct timespec m_prev_table_update;
111         int m_table_cnt;
112 public:
113
114         eAUTable()
115         {
116         }
117
118         ~eAUTable()
119         {
120                 stop();
121         }
122         
123         void stop()
124         {
125                 current = next = 0;
126                 m_demux = 0;
127         }
128         
129         int begin(eMainloop *m, const eDVBTableSpec &spec, ePtr<iDVBDemux> demux)
130         {
131                 m_table_cnt = 0;
132                 ml = m;
133                 m_demux = demux;
134                 first= 1;
135                 current = 0;
136                 next = new Table();
137                 CONNECT(next->tableReady, eAUTable::slotTableReady);
138                 next->start(demux, spec);
139                 return 0;
140         }
141         
142         int get()
143         {
144                 if (current)
145                 {
146                         /*emit*/ tableReady(0);
147                         return 0;
148                 } else if (!next)
149                 {
150                         /*emit*/ tableReady(-1);
151                         return 0;
152                 } else
153                         return 1;
154         }
155         
156         RESULT getCurrent(ePtr<Table> &ptr)
157         {
158                 if (!current)
159                         return -1;
160                 ptr = current;
161                 return 0;
162         }
163
164 #if 0   
165         void abort()
166         {
167                 eDebug("eAUTable: aborted!");
168                 if (next)
169                         next->abort();
170                 delete next;
171                 next=0;
172         }
173 #endif
174
175         int ready()
176         {
177                 return !!current;
178         }
179         
180         void inject(Table *t)
181         {
182                 next=t;
183                 getNext(0);
184         }
185
186         void getNext(int error)
187         {
188                 current = 0;
189                 if (error)
190                 {
191                         next=0;
192                         if (first)
193                                 /*emit*/ tableReady(error);
194                         first=0;
195                         return;
196                 } else
197                         current=next;
198
199                 next=0;
200                 first=0;
201                 
202                 ASSERT(current->ready);
203                         
204                 /*emit*/ tableReady(0);
205                 
206                 eDVBTableSpec spec;
207
208                 if (current && (!current->getSpec(spec)))
209                 {
210                         /* detect broken table version handling (seen on some m2ts files) */
211                         if (m_table_cnt)
212                         {
213                                 if (abs(timeout_usec(m_prev_table_update)) > 500000)
214                                         m_table_cnt = -1;
215                                 else if (m_table_cnt > 1) // two pmt update within one second
216                                 {
217                                         eDebug("Seen two consecutive table version changes within 500ms. "
218                                             "This seems broken, so auto update for pid %04x, table %02x is now disabled!!",
219                                             spec.pid, spec.tid);
220                                         m_table_cnt = 0;
221                                         return;
222                                 }
223                         }
224
225                         ++m_table_cnt;
226                         clock_gettime(CLOCK_MONOTONIC, &m_prev_table_update);
227
228                         next = new Table();
229                         CONNECT(next->tableReady, eAUTable::slotTableReady);
230                         spec.flags &= ~(eDVBTableSpec::tfAnyVersion|eDVBTableSpec::tfThisVersion|eDVBTableSpec::tfHaveTimeout);
231                         next->eGTable::start(m_demux, spec);
232                 }
233         }
234 };
235
236 #endif