now its possible to call ePixmap.setPixmap from python without use of
[enigma2.git] / lib / dvb / radiotext.cpp
1 #include <lib/base/eerror.h>
2 #include <lib/dvb/radiotext.h>
3 #include <lib/dvb/idemux.h>
4 #include <lib/gdi/gpixmap.h>
5
6 DEFINE_REF(eDVBRadioTextParser);
7
8 eDVBRadioTextParser::eDVBRadioTextParser(iDVBDemux *demux)
9         :bytesread(0), ptr(0), p1(-1), p2(-1), msgPtr(0), state(0)
10         ,m_abortTimer(eApp)
11 {
12         setStreamID(0xC0, 0xC0);
13
14         if (demux->createPESReader(eApp, m_pes_reader))
15                 eDebug("failed to create PES reader!");
16         else
17                 m_pes_reader->connectRead(slot(*this, &eDVBRadioTextParser::processData), m_read_connection);
18         CONNECT(m_abortTimer.timeout, eDVBRadioTextParser::abortNonAvail);
19 }
20
21 #define SWAP(x) ((x<<8)|(x>>8))
22 #define LO(x)   (x&0xFF)
23
24 static inline unsigned short crc_ccitt_byte( unsigned short crc, unsigned char c )
25 {
26         crc = SWAP(crc) ^ c;
27         crc = crc ^ (LO(crc) >> 4);
28         crc = crc ^ (SWAP(LO(crc)) << 4) ^ (LO(crc) << 5);
29         return crc;
30 }
31
32 static int bitrate[3][3][16] = {
33         {
34                 // MPEG-2, L3
35                 {-1,8000,16000,24000,32000,40000,48000,56000,64000,80000,96000,112000,128000,144000,160000,0}, 
36                 // MPEG-2, L2
37                 {-1,8000,16000,24000,32000,40000,48000,56000,64000,80000,96000,112000,128000,144000,160000,0},
38                 // MPEG-2, L1
39                 {-1,32000,48000,56000,64000,80000,96000,112000,128000,144000,160000,176000,192000,224000,256000,0}
40         },
41         {
42                 // MPEG-1, L3
43                 {-1,32000,40000,48000,56000,64000,80000,96000,112000,128000,160000,192000,224000,256000,320000,0}, 
44                 // MPEG-1, L2
45                 {-1,32000,48000,56000,64000,80000,96000,112000,128000,160000,192000,224000,256000,320000,384000,0},
46                 // MPEG-1, L1
47                 {-1,32000,64000,96000,128000,160000,192000,224000,256000,288000,320000,352000,384000,416000,448000,0}
48         },
49         {
50                 //MPEG-2.5, L3??
51                 {-1,6000,8000,10000,12000,16000,20000,24000,28000,320000,40000,48000,56000,64000,80000,0},
52                 //MPEG-2.5, L2
53                 {-1,6000,8000,10000,12000,16000,20000,24000,28000,320000,40000,48000,56000,64000,80000,0},
54                 //MPEG-2.5, L1
55                 {-1,8000,12000,16000,20000,24000,32000,40000,48000,560000,64000,80000,96000,112000,128000,0}
56         }
57 };
58
59 static int frequency[3][4] = {
60         // MPEG2 - 22.05, 24, 16khz
61         { 22050,24000,16000,0 },
62         // MPEG1 - 44.1, 48, 32khz
63         { 44100,48000,32000,0 },
64         // MPEG2.5 - 11.025, 12, 8khz
65         { 11025,12000,8000,0 }
66 };
67
68 void eDVBRadioTextParser::connectUpdatedRadiotext(const Slot0<void> &slot, ePtr<eConnection> &connection)
69 {
70         connection = new eConnection(this, m_updated_radiotext.connect(slot));
71 }
72
73 void eDVBRadioTextParser::processPESPacket(__u8 *data, int len)
74 {
75         int pos=9+data[8];// skip pes header
76
77         while (pos < len)
78         {
79                 if ((0xFF & data[pos]) != 0xFF || (0xF0 & data[pos + 1]) != 0xF0)
80                         return;
81
82                 int padding_bit = (data[pos + 2]>>1) & 1;
83                 int mode = (data[pos + 3]>>6) & 3;
84                 int channel = mode == 3 ? 1 : 2;
85                 int id = (data[pos + 1] >> 3) & 1;
86                 int emphasis_bit = data[pos + 3] & 3;
87                 int protection_bit = data[pos + 1] & 1;
88                 int rate = -1;
89                 int sample_freq = -1;
90                 int layer = -1;
91
92                 if (emphasis_bit == 2 && id == 1 )
93                         id = 2;
94
95                 if ((layer = (data[pos + 1]>>1) & 3) < 1)
96                         return;
97
98                 if ((rate = bitrate[id][layer - 1][(data[pos + 2]>>4) & 0xf]) < 1)
99                         return;
100
101                 if ((sample_freq = frequency[id][(data[pos + 2]>>2) & 3]) == 0)
102                         return;
103
104                 if (id == 1 && layer == 2)
105                 {
106                         if (rate / channel < 32000)
107                                 return;
108                         if (rate / channel > 192000)
109                                 return;
110                 }
111
112                 int frame_size = layer < 3 ?
113                         (144 * rate / sample_freq) + padding_bit :
114                         ((12 * rate / sample_freq) * 4) + (4 * padding_bit);
115
116                 pos += frame_size;
117
118 #if 0
119 //              eDebug("protection_bit ? %d", protection_bit);
120 //              int offs = protection_bit ? pos - 1 : pos - 3;
121 //              if (data[offs] != 0xFD)
122 //                      offs += 2;
123 //              eDebug("%02x %02x %02x %02x %02x", data[offs-2], data[offs-1], data[offs], data[offs+1], data[offs+2]);
124 #else
125                 int offs = pos - 1;
126 #endif
127
128                 if (data[offs] == 0xFD)
129                 {
130                         m_abortTimer.stop();
131                         int ancillary_len = 1 + data[offs - 1];
132                         offs -= ancillary_len;
133                         while(offs < pos)
134                                 gotAncillaryByte(data[offs++]);
135                 }
136         }
137 }
138
139 inline void eDVBRadioTextParser::gotAncillaryByte(__u8 data)
140 {
141         buf[bytesread]=data;
142         bytesread+=1;
143         if ( bytesread == 128 )
144         {
145                 while(ptr<128)
146                 {
147                         if ( buf[ptr] == 0xFD )
148                         {
149                                 if (p1 == -1)
150                                         p1 = ptr;
151                                 else
152                                         p2 = ptr;
153                         }
154                         if ( p1 != -1 && p2 != -1 )
155                         {
156                                 int cnt=buf[--p2];
157                                 while ( cnt-- > 0 )
158                                 {
159                                         unsigned char c = buf[--p2];
160                                         if ( state == 1 )
161                                                 crc=0xFFFF;
162                                         if ( state >= 1 && state < 11 )
163                                                 crc = crc_ccitt_byte(crc, c);
164
165                                         switch (state)
166                                         {
167                                                 case 0:
168                                                         if ( c==0xFE )  // Startkennung
169                                                                 state=1;
170                                                         break;
171                                                 case 1: // 10bit Site Address + 6bit Encoder Address
172                                                 case 2:
173                                                 case 3: // Sequence Counter
174                                                         ++state;
175                                                         break;
176                                                 case 4:
177                                                         leninfo=c;
178                                                         ++state;
179                                                         break;
180                                                 case 5:
181                                                         if ( c==0x0A ) // message element code 0x0A Radio Text
182                                                                 ++state;
183                                                         else
184                                                                 state=0;
185                                                         break;
186                                                 case 6: // Data Set Number ... ignore
187                                                 case 7: // Program Service Number ... ignore
188                                                         ++state;
189                                                         break;
190                                                 case 8: // Message Element Length
191                                                         todo=c;
192                                                         if ( !todo || todo > 65 || todo > leninfo-4)
193                                                                 state=0;
194                                                         else
195                                                         {
196                                                                 ++state;
197                                                                 todo-=2;
198                                                                 msgPtr=0;
199                                                         }
200                                                         break;
201                                                 case 9: // Radio Text Status bit:
202                                                         // 0   = AB-flagcontrol
203                                                         // 1-4 = Transmission-Number
204                                                         // 5-6 = Buffer-Config
205                                                         ++state; // ignore ...
206                                                         break;
207                                                 case 10:
208         // TODO build a complete radiotext charcode to UTF8 conversion table for all character > 0x80
209                                                         switch (c)
210                                                         {
211                                                                 case 0 ... 0x7f: break;
212                                                                 case 0x8d: c='ß'; break;
213                                                                 case 0x91: c='ä'; break;
214                                                                 case 0xd1: c='Ä'; break;
215                                                                 case 0x97: c='ö'; break;
216                                                                 case 0xd7: c='Ö'; break;
217                                                                 case 0x99: c='ü'; break;
218                                                                 case 0xd9: c='Ü'; break;
219                                                                 default: c=' '; break;  // convert all unknown to space
220                                                         }
221                                                         message[msgPtr++]=c;
222                                                         if(todo)
223                                                                 --todo;
224                                                         else
225                                                                 ++state;
226                                                         break;
227                                                 case 11:
228                                                         crc16=c<<8;
229                                                         ++state;
230                                                         break;
231                                                 case 12:
232                                                         crc16|=c;
233                                                         message[msgPtr--]=0;
234                                                         while(message[msgPtr] == ' ' && msgPtr > 0)
235                                                                 message[msgPtr--] = 0;
236                                                         if ( crc16 == (crc^0xFFFF) )
237                                                         {
238                                                                 eDebug("radiotext: (%s)", message);
239                                                                 /*emit*/ m_updated_radiotext();
240                                                         }
241                                                         else
242                                                                 eDebug("invalid radiotext crc (%s)", message);
243                                                         state=0;
244                                                         break;
245                                         }
246                                 }
247                                 p1=ptr;
248                                 p2=-1;
249                         }
250                         ++ptr;
251                 }
252                 if (p1 != -1 && (128-p1) != 128)
253                 {
254                         bytesread=ptr=128-p1;
255                         memcpy(buf, buf+p1, ptr);
256                         p1=0;
257                 }
258                 else
259                         bytesread=ptr=0;
260         }
261 }
262
263 int eDVBRadioTextParser::start(int pid)
264 {
265         int ret = -1;
266         if (m_pes_reader && !(ret = m_pes_reader->start(pid)))
267                 m_abortTimer.startLongTimer(20);
268         return ret;
269 }
270
271 void eDVBRadioTextParser::abortNonAvail()
272 {
273         eDebug("no ancillary data in audio stream... abort radiotext pes parser");
274         if (m_pes_reader)
275                 m_pes_reader->stop();
276 }