1 #include <lib/base/eerror.h>
2 #include <lib/dvb/radiotext.h>
3 #include <lib/dvb/idemux.h>
4 #include <lib/gdi/gpixmap.h>
6 DEFINE_REF(eDVBRadioTextParser);
8 eDVBRadioTextParser::eDVBRadioTextParser(iDVBDemux *demux)
9 :bytesread(0), ptr(0), p1(-1), p2(-1), msgPtr(0), state(0)
11 setStreamID(0xC0, 0xC0);
13 if (demux->createPESReader(eApp, m_pes_reader))
14 eDebug("failed to create PES reader!");
16 m_pes_reader->connectRead(slot(*this, &eDVBRadioTextParser::processData), m_read_connection);
19 #define SWAP(x) ((x<<8)|(x>>8))
20 #define LO(x) (x&0xFF)
22 static inline unsigned short crc_ccitt_byte( unsigned short crc, unsigned char c )
25 crc = crc ^ (LO(crc) >> 4);
26 crc = crc ^ (SWAP(LO(crc)) << 4) ^ (LO(crc) << 5);
30 static int bitrate[3][3][16] = {
33 {-1,8000,16000,24000,32000,40000,48000,56000,64000,80000,96000,112000,128000,144000,160000,0},
35 {-1,8000,16000,24000,32000,40000,48000,56000,64000,80000,96000,112000,128000,144000,160000,0},
37 {-1,32000,48000,56000,64000,80000,96000,112000,128000,144000,160000,176000,192000,224000,256000,0}
41 {-1,32000,40000,48000,56000,64000,80000,96000,112000,128000,160000,192000,224000,256000,320000,0},
43 {-1,32000,48000,56000,64000,80000,96000,112000,128000,160000,192000,224000,256000,320000,384000,0},
45 {-1,32000,64000,96000,128000,160000,192000,224000,256000,288000,320000,352000,384000,416000,448000,0}
49 {-1,6000,8000,10000,12000,16000,20000,24000,28000,320000,40000,48000,56000,64000,80000,0},
51 {-1,6000,8000,10000,12000,16000,20000,24000,28000,320000,40000,48000,56000,64000,80000,0},
53 {-1,8000,12000,16000,20000,24000,32000,40000,48000,560000,64000,80000,96000,112000,128000,0}
57 static int frequency[3][4] = {
58 // MPEG2 - 22.05, 24, 16khz
59 { 22050,24000,16000,0 },
60 // MPEG1 - 44.1, 48, 32khz
61 { 44100,48000,32000,0 },
62 // MPEG2.5 - 11.025, 12, 8khz
63 { 11025,12000,8000,0 }
66 void eDVBRadioTextParser::connectUpdatedRadiotext(const Slot0<void> &slot, ePtr<eConnection> &connection)
68 connection = new eConnection(this, m_updated_radiotext.connect(slot));
71 void eDVBRadioTextParser::processPESPacket(__u8 *data, int len)
73 int pos=9+data[8];// skip pes header
77 if ((0xFF & data[pos]) != 0xFF || (0xF0 & data[pos + 1]) != 0xF0)
80 int padding_bit = (data[pos + 2]>>1) & 1;
81 int mode = (data[pos + 3]>>6) & 3;
82 int channel = mode == 3 ? 1 : 2;
83 int id = (data[pos + 1] >> 3) & 1;
84 int emphasis_bit = data[pos + 3] & 3;
85 int protection_bit = data[pos + 1] & 1;
90 if (emphasis_bit == 2 && id == 1 )
93 if ((layer = (data[pos + 1]>>1) & 3) < 1)
96 if ((rate = bitrate[id][layer - 1][(data[pos + 2]>>4) & 0xf]) < 1)
99 if ((sample_freq = frequency[id][(data[pos + 2]>>2) & 3]) == 0)
102 if (id == 1 && layer == 2)
104 if (rate / channel < 32000)
106 if (rate / channel > 192000)
110 int frame_size = layer < 3 ?
111 (144 * rate / sample_freq) + padding_bit :
112 ((12 * rate / sample_freq) * 4) + (4 * padding_bit);
117 // eDebug("protection_bit ? %d", protection_bit);
118 // int offs = protection_bit ? pos - 1 : pos - 3;
119 // if (data[offs] != 0xFD)
121 // eDebug("%02x %02x %02x %02x %02x", data[offs-2], data[offs-1], data[offs], data[offs+1], data[offs+2]);
126 if (data[offs] == 0xFD)
128 int ancillary_len = 1 + data[offs - 1];
129 offs -= ancillary_len;
131 gotAncillaryByte(data[offs++]);
136 void eDVBRadioTextParser::gotAncillaryByte(__u8 data)
140 if ( bytesread == 128 )
144 if ( buf[ptr] == 0xFD )
151 if ( p1 != -1 && p2 != -1 )
156 unsigned char c = buf[--p2];
159 if ( state >= 1 && state < 11 )
160 crc = crc_ccitt_byte(crc, c);
165 if ( c==0xFE ) // Startkennung
168 case 1: // 10bit Site Address + 6bit Encoder Address
170 case 3: // Sequence Counter
178 if ( c==0x0A ) // message element code 0x0A Radio Text
183 case 6: // Data Set Number ... ignore
184 case 7: // Program Service Number ... ignore
187 case 8: // Message Element Length
189 if ( !todo || todo > 65 || todo > leninfo-4)
198 case 9: // Radio Text Status bit:
199 // 0 = AB-flagcontrol
200 // 1-4 = Transmission-Number
201 // 5-6 = Buffer-Config
202 ++state; // ignore ...
205 // TODO build a complete radiotext charcode to UTF8 conversion table for all character > 0x80
208 case 0 ... 0x7f: break;
209 case 0x8d: c='ß'; break;
210 case 0x91: c='ä'; break;
211 case 0xd1: c='Ä'; break;
212 case 0x97: c='ö'; break;
213 case 0xd7: c='Ö'; break;
214 case 0x99: c='ü'; break;
215 case 0xd9: c='Ü'; break;
216 default: c=' '; break; // convert all unknown to space
231 while(message[msgPtr] == ' ' && msgPtr > 0)
232 message[msgPtr--] = 0;
233 if ( crc16 == (crc^0xFFFF) )
235 eDebug("radiotext: (%s)", message);
236 /*emit*/ m_updated_radiotext();
239 eDebug("invalid radiotext crc (%s)", message);
249 if (p1 != -1 && (128-p1) != 128)
251 bytesread=ptr=128-p1;
252 memcpy(buf, buf+p1, ptr);
260 int eDVBRadioTextParser::start(int pid)
263 return m_pes_reader->start(pid);