it doesn't compile with const
[enigma2.git] / lib / dvb / pmt.cpp
1 #include <lib/base/eerror.h>
2 #include <lib/dvb/pmt.h>
3 #include <lib/dvb/specs.h>
4 #include <lib/dvb/dvb.h>
5 #include <lib/dvb/metaparser.h>
6 #include <dvbsi++/ca_program_map_section.h>
7
8 eDVBServicePMTHandler::eDVBServicePMTHandler(int record)
9         :m_ca_servicePtr(0)
10 {
11         m_record = record;
12         eDVBResourceManager::getInstance(m_resourceManager);
13         CONNECT(m_PMT.tableReady, eDVBServicePMTHandler::PMTready);
14         CONNECT(m_PAT.tableReady, eDVBServicePMTHandler::PATready);
15         eDebug("new PMT handler record: %d", m_record);
16 }
17
18 eDVBServicePMTHandler::~eDVBServicePMTHandler()
19 {
20         eDebug("delete PMT handler record: %d", m_record);
21         if (m_ca_servicePtr)
22         {
23                 eDebug("unregister caservice");
24                 uint8_t demux_num;
25                 m_demux->getCADemuxID(demux_num);
26                 ePtr<eTable<ProgramMapSection> > ptr;
27                 m_PMT.getCurrent(ptr);
28                 eDVBCAService::unregister_demux(m_reference, demux_num, ptr);
29         }
30 }
31
32 void eDVBServicePMTHandler::channelStateChanged(iDVBChannel *channel)
33 {
34         int state;
35         channel->getState(state);
36         
37         if ((m_last_channel_state != iDVBChannel::state_ok)
38                 && (state == iDVBChannel::state_ok) && (!m_demux))
39         {
40                 if (m_channel)
41                         if (m_channel->getDemux(m_demux, m_record ? 0 : iDVBChannel::capDecode))
42                                 eDebug("Allocating a demux for now tuned-in channel failed.");
43                 
44                 serviceEvent(eventTuned);
45                 
46                 if (m_demux)
47                 {
48                         eDebug("ok ... now we start!!");
49
50                         /* emit */ m_resourceManager->m_channelRunning(channel);
51
52                         m_PAT.begin(eApp, eDVBPATSpec(), m_demux);
53
54                         if ( m_service && !m_service->cacheEmpty() )
55                                 serviceEvent(eventNewProgramInfo);
56                 }
57         } else if ((m_last_channel_state != iDVBChannel::state_failed) && 
58                         (state == iDVBChannel::state_failed))
59         {
60                 eDebug("tune failed.");
61                 serviceEvent(eventTuneFailed);
62         }
63 }
64
65 void eDVBServicePMTHandler::PMTready(int error)
66 {
67         if (error)
68                 serviceEvent(eventNoPMT);
69         else
70         {
71                 serviceEvent(eventNewProgramInfo);
72                 if (!m_pvr_channel && !m_ca_servicePtr)   // don't send campmt to camd.socket for playbacked services
73                 {
74                         uint8_t demux_num;
75                         m_demux->getCADemuxID(demux_num);
76                         eDVBCAService::register_demux(m_reference, demux_num, m_ca_servicePtr);
77                 }
78                 if (m_ca_servicePtr)
79                 {
80                         ePtr<eTable<ProgramMapSection> > ptr;
81                         if (!m_PMT.getCurrent(ptr))
82                                 m_ca_servicePtr->buildCAPMT(ptr);
83                         else
84                                 eDebug("eDVBServicePMTHandler cannot call buildCAPMT");
85                 }
86         }
87 }
88
89 void eDVBServicePMTHandler::PATready(int)
90 {
91         eDebug("got PAT");
92         ePtr<eTable<ProgramAssociationSection> > ptr;
93         if (!m_PAT.getCurrent(ptr))
94         {
95                 int pmtpid = -1;
96                 std::vector<ProgramAssociationSection*>::const_iterator i;
97                 for (i = ptr->getSections().begin(); i != ptr->getSections().end(); ++i)
98                 {
99                         const ProgramAssociationSection &pat = **i;
100                         ProgramAssociationConstIterator program;
101                         for (program = pat.getPrograms()->begin(); program != pat.getPrograms()->end(); ++program)
102                                 if (eServiceID((*program)->getProgramNumber()) == m_reference.getServiceID())
103                                         pmtpid = (*program)->getProgramMapPid();
104                 }
105                 if (pmtpid == -1)
106                         serviceEvent(eventNoPATEntry);
107                 else
108                         m_PMT.begin(eApp, eDVBPMTSpec(pmtpid, m_reference.getServiceID().get()), m_demux);
109         } else
110                 serviceEvent(eventNoPAT);
111 }
112
113 int eDVBServicePMTHandler::getProgramInfo(struct program &program)
114 {
115         ePtr<eTable<ProgramMapSection> > ptr;
116
117         program.videoStreams.clear();
118         program.audioStreams.clear();
119         program.pcrPid = -1;
120
121         if (!m_PMT.getCurrent(ptr))
122         {
123                 eDVBTableSpec table_spec;
124                 ptr->getSpec(table_spec);
125                 program.pmtPid = table_spec.pid < 0x1fff ? table_spec.pid : -1;
126                 std::vector<ProgramMapSection*>::const_iterator i;
127                 for (i = ptr->getSections().begin(); i != ptr->getSections().end(); ++i)
128                 {
129                         const ProgramMapSection &pmt = **i;
130                         program.pcrPid = pmt.getPcrPid();
131                         
132                         ElementaryStreamInfoConstIterator es;
133                         for (es = pmt.getEsInfo()->begin(); es != pmt.getEsInfo()->end(); ++es)
134                         {
135                                 int isaudio = 0, isvideo = 0;
136                                 videoStream video;
137                                 audioStream audio;
138                                 
139                                 video.pid = (*es)->getPid();
140                                 audio.pid = (*es)->getPid();
141                                 
142                                 switch ((*es)->getType())
143                                 {
144                                 case 0x01: // MPEG 1 video
145                                 case 0x02: // MPEG 2 video
146                                         isvideo = 1;
147                                         break;
148                                 case 0x03: // MPEG 1 audio
149                                 case 0x04: // MPEG 2 audio:
150                                         isaudio = 1;
151                                         audio.type = audioStream::atMPEG;
152                                         break;
153                                 }
154                                 if (isaudio)
155                                         program.audioStreams.push_back(audio);
156                                 if (isvideo)
157                                         program.videoStreams.push_back(video);
158                         }
159                 }
160                 return 0;
161         }
162         else if ( m_service && !m_service->cacheEmpty() )
163         {
164                 int vpid = m_service->getCachePID(eDVBService::cVPID),
165                         apid_ac3 = m_service->getCachePID(eDVBService::cAPID),
166                         apid_mpeg = m_service->getCachePID(eDVBService::cAC3PID),
167                         pcrpid = m_service->getCachePID(eDVBService::cPCRPID),
168                         cnt=0;
169                 if ( vpid != -1 )
170                 {
171                         videoStream s;
172                         s.pid = vpid;
173                         program.videoStreams.push_back(s);
174                         ++cnt;
175                 }
176                 if ( apid_ac3 != -1 )
177                 {
178                         audioStream s;
179                         s.type = audioStream::atAC3;
180                         s.pid = apid_ac3;
181                         program.audioStreams.push_back(s);
182                         ++cnt;
183                 }
184                 if ( apid_mpeg != -1 )
185                 {
186                         audioStream s;
187                         s.type = audioStream::atMPEG;
188                         s.pid = apid_mpeg;
189                         program.audioStreams.push_back(s);
190                         ++cnt;
191                 }
192                 if ( pcrpid != -1 )
193                 {
194                         ++cnt;
195                         program.pcrPid = pcrpid;
196                 }
197                 if ( cnt )
198                         return 0;
199         }
200         return -1;
201 }
202
203 int eDVBServicePMTHandler::getDemux(ePtr<iDVBDemux> &demux)
204 {
205         demux = m_demux;
206         if (demux)
207                 return 0;
208         else
209                 return -1;
210 }
211
212 int eDVBServicePMTHandler::getPVRChannel(ePtr<iDVBPVRChannel> &pvr_channel)
213 {
214         pvr_channel = m_pvr_channel;
215         if (pvr_channel)
216                 return 0;
217         else
218                 return -1;
219 }
220
221 int eDVBServicePMTHandler::tune(eServiceReferenceDVB &ref)
222 {
223         RESULT res;
224         m_reference = ref;
225         
226                 /* is this a normal (non PVR) channel? */
227         if (ref.path.empty())
228         {
229                 eDVBChannelID chid;
230                 ref.getChannelID(chid);
231                 res = m_resourceManager->allocateChannel(chid, m_channel);
232                 eDebug("allocate Channel: res %d", res);
233         } else
234         {
235                 eDVBMetaParser parser;
236                 
237                 if (parser.parseFile(ref.path))
238                         eWarning("no .meta file found, trying original service ref.");
239                 else
240                         m_reference = parser.m_ref;
241                 
242                 eDebug("alloc PVR");
243                         /* allocate PVR */
244                 res = m_resourceManager->allocatePVRChannel(m_pvr_channel);
245                 if (res)
246                         eDebug("allocatePVRChannel failed!\n");
247                 m_channel = m_pvr_channel;
248         }
249         
250         if (m_channel)
251         {
252                 m_channel->connectStateChange(
253                         slot(*this, &eDVBServicePMTHandler::channelStateChanged), 
254                         m_channelStateChanged_connection);
255                 m_last_channel_state = -1;
256                 channelStateChanged(m_channel);
257         } else
258         {
259                 serviceEvent(eventTuneFailed);
260                 return res;
261         }
262
263         if (m_pvr_channel)
264                 m_pvr_channel->playFile(ref.path.c_str());
265
266         ePtr<iDVBChannelList> db;
267         if (!m_resourceManager->getChannelList(db))
268                 db->getService((eServiceReferenceDVB&)m_reference, m_service);
269
270         return res;
271 }
272
273 std::map<eServiceReferenceDVB, eDVBCAService*> eDVBCAService::exist;
274
275 eDVBCAService::eDVBCAService()
276         :m_prev_build_hash(0), m_sendstate(0), m_retryTimer(eApp)
277 {
278         memset(m_used_demux, 0xFF, sizeof(m_used_demux));
279         CONNECT(m_retryTimer.timeout, eDVBCAService::sendCAPMT);
280         Connect();
281 }
282
283 eDVBCAService::~eDVBCAService()
284 {
285         eDebug("[eDVBCAService] free service %s", m_service.toString().c_str());
286         ::close(m_sock);
287 }
288
289 RESULT eDVBCAService::register_demux( const eServiceReferenceDVB &ref, int demux_num, eDVBCAService *&caservice )
290 {
291         CAServiceMap::iterator it = exist.find(ref);
292         if ( it != exist.end() )
293                 caservice = it->second;
294         else
295         {
296                 caservice = (exist[ref]=new eDVBCAService());
297                 caservice->m_service = ref;
298                 eDebug("[eDVBCAHandler] new service %s", ref.toString().c_str() );
299         }
300 // search free demux entry
301         int iter=0, max_demux_slots = sizeof(caservice->m_used_demux);
302
303         while ( iter < max_demux_slots && caservice->m_used_demux[iter] != 0xFF )
304                 ++iter;
305
306         if ( iter < max_demux_slots )
307         {
308                 caservice->m_used_demux[iter] = demux_num & 0xFF;
309                 eDebug("[eDVBCAHandler] add demux %d to slot %d service %s", demux_num, iter, ref.toString().c_str());
310         }
311         else
312         {
313                 eDebug("[eDVBCAHandler] no more demux slots free for service %s!!", ref.toString().c_str());
314                 return -1;
315         }
316         return 0;
317 }
318
319 RESULT eDVBCAService::unregister_demux( const eServiceReferenceDVB &ref, int demux_num, eTable<ProgramMapSection> *ptr )
320 {
321         CAServiceMap::iterator it = exist.find(ref);
322         if ( it == exist.end() )
323         {
324                 eDebug("[eDVBCAHandler] try to unregister non registered %s", ref.toString().c_str());
325                 return -1;
326         }
327         else
328         {
329                 eDVBCAService *caservice = it->second;
330                 bool freed = false;
331                 int iter = 0,
332                         used_demux_slots = 0,
333                         max_demux_slots = sizeof(caservice->m_used_demux)/sizeof(int);
334                 while ( iter < max_demux_slots )
335                 {
336                         if ( caservice->m_used_demux[iter] != 0xFF )
337                         {
338                                 if ( !freed && caservice->m_used_demux[iter] == demux_num )
339                                 {
340                                         eDebug("[eDVBCAService] free slot %d demux %d for service %s", iter, caservice->m_used_demux[iter], caservice->m_service.toString().c_str() );
341                                         caservice->m_used_demux[iter] = 0xFF;
342                                         freed=true;
343                                 }
344                                 else
345                                         ++used_demux_slots;
346                         }
347                         ++iter;
348                 }
349                 if (!freed)
350                 {
351                         eDebug("[eDVBCAService] couldn't free demux slot for demux %d", demux_num);
352                         return -1;
353                 }
354                 if (!used_demux_slots)  // no more used.. so we remove it
355                 {
356                         delete it->second;
357                         exist.erase(it);
358                 }
359                 else
360                 {
361                         if (ptr)
362                                 it->second->buildCAPMT(ptr);
363                         else
364                                 eDebug("[eDVBCAHandler] can not send updated demux info");
365                 }
366         }
367         return 0;
368 }
369
370 void eDVBCAService::Connect()
371 {
372         memset(&m_servaddr, 0, sizeof(struct sockaddr_un));
373         m_servaddr.sun_family = AF_UNIX;
374         strcpy(m_servaddr.sun_path, "/tmp/camd.socket");
375         m_clilen = sizeof(m_servaddr.sun_family) + strlen(m_servaddr.sun_path);
376         m_sock = socket(PF_UNIX, SOCK_STREAM, 0);
377         connect(m_sock, (struct sockaddr *) &m_servaddr, m_clilen);
378         fcntl(m_sock, F_SETFL, O_NONBLOCK);
379         int val=1;
380         setsockopt(m_sock, SOL_SOCKET, SO_REUSEADDR, &val, 4);
381 }
382
383 void eDVBCAService::buildCAPMT(eTable<ProgramMapSection> *ptr)
384 {
385         if (!ptr)
386                 return;
387
388         eDVBTableSpec table_spec;
389         ptr->getSpec(table_spec);
390
391         int pmtpid = table_spec.pid,
392                 pmt_version = table_spec.version;
393
394         uint8_t demux_mask = 0;
395         uint8_t first_demux_num = 0xFF;
396
397         int iter=0, max_demux_slots = sizeof(m_used_demux);
398         while ( iter < max_demux_slots )
399         {
400                 if ( m_used_demux[iter] != 0xFF )
401                 {
402                         if ( first_demux_num == 0xFF )
403                                 first_demux_num = m_used_demux[iter];
404                         demux_mask |= (1 << m_used_demux[iter]);
405                 }
406                 ++iter;
407         }
408
409         if ( first_demux_num == 0xFF )
410         {
411                 eDebug("[eDVBCAService] no demux found for service %s", m_service.toString().c_str() );
412                 return;
413         }
414
415         eDebug("demux %d mask %02x prevhash %08x", first_demux_num, demux_mask, m_prev_build_hash);
416
417         unsigned int build_hash = (pmtpid << 16);
418         build_hash |= (demux_mask << 8);
419         build_hash |= (pmt_version&0xFF);
420
421         if ( build_hash == m_prev_build_hash )
422         {
423                 eDebug("[eDVBCAService] don't build/send the same CA PMT twice");
424                 return;
425         }
426
427         std::vector<ProgramMapSection*>::const_iterator i=ptr->getSections().begin();
428         if ( i != ptr->getSections().end() )
429         {
430                 CaProgramMapSection capmt(*i++, m_prev_build_hash ? 0x05 /*update*/ : 0x03 /*only*/, 0x01 );
431
432                 while( i != ptr->getSections().end() )
433                 {
434 //                      eDebug("append");
435                         capmt.append(*i++);
436                 }
437
438                 // add our private descriptors to capmt
439                 uint8_t tmp[10];
440
441                 tmp[0]=0x84;  // pmt pid
442                 tmp[1]=0x02;
443                 tmp[2]=pmtpid>>8;
444                 tmp[3]=pmtpid&0xFF;
445                 capmt.injectDescriptor(tmp, false);
446
447                 tmp[0] = 0x82; // demux
448                 tmp[1] = 0x02;
449                 tmp[3] = first_demux_num; // read section data from demux number
450                 tmp[2] = demux_mask;    // descramble bitmask
451                 capmt.injectDescriptor(tmp, false);
452
453                 tmp[0] = 0x81; // dvbnamespace
454                 tmp[1] = 0x08;
455                 tmp[2] = m_service.getDVBNamespace().get()>>24;
456                 tmp[3]=(m_service.getDVBNamespace().get()>>16)&0xFF;
457                 tmp[4]=(m_service.getDVBNamespace().get()>>8)&0xFF;
458                 tmp[5]=m_service.getDVBNamespace().get()&0xFF;
459                 tmp[6]=m_service.getTransportStreamID().get()>>8;
460                 tmp[7]=m_service.getTransportStreamID().get()&0xFF;
461                 tmp[8]=m_service.getOriginalNetworkID().get()>>8;
462                 tmp[9]=m_service.getOriginalNetworkID().get()&0xFF;
463                 capmt.injectDescriptor(tmp, false);
464
465                 capmt.writeToBuffer(m_capmt);
466         }
467
468         m_prev_build_hash = build_hash;
469
470         if ( m_sendstate != 0xFFFFFFFF )
471                 m_sendstate=0;
472         sendCAPMT();
473 }
474
475 void eDVBCAService::sendCAPMT()
476 {
477         if ( m_sendstate && m_sendstate != 0xFFFFFFFF ) // broken pipe retry
478         {
479                 ::close(m_sock);
480                 Connect();
481         }
482
483         int wp=0;
484         if ( m_capmt[3] & 0x80 )
485         {
486                 int i=0;
487                 int lenbytes = m_capmt[3] & ~0x80;
488                 while(i < lenbytes)
489                         wp |= (m_capmt[4+i] << (8 * i++));
490                 wp+=4;
491                 wp+=lenbytes;
492         }
493         else
494         {
495                 wp = m_capmt[3];
496                 wp+=4;
497         }
498
499         if ( write(m_sock, m_capmt, wp) == wp )
500         {
501                 m_sendstate=0xFFFFFFFF;
502                 eDebug("[eDVBCAHandler] send %d bytes",wp);
503 #if 1
504                 for(int i=0;i<wp;i++)
505                         eDebugNoNewLine("%02x ", m_capmt[i]);
506                 eDebug("");
507 #endif
508         }
509         else
510         {
511                 switch(m_sendstate)
512                 {
513                         case 0xFFFFFFFF:
514                                 ++m_sendstate;
515                                 m_retryTimer.start(0,true);
516 //                              eDebug("[eDVBCAHandler] send failed .. immediate retry");
517                                 break;
518                         default:
519                                 m_retryTimer.start(5000,true);
520 //                              eDebug("[eDVBCAHandler] send failed .. retry in 5 sec");
521                                 break;
522                 }
523                 ++m_sendstate;
524         }
525 }