get rid of unneeded for loop .. do recursion now
[enigma2.git] / lib / dvb / dvb.cpp
1 #include <lib/base/eerror.h>
2 #include <lib/base/filepush.h>
3 #include <lib/dvb/idvb.h>
4 #include <lib/dvb/dvb.h>
5 #include <lib/dvb/sec.h>
6
7 #include <errno.h>
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <unistd.h>
11 #include <fcntl.h>
12 #include <sys/ioctl.h>
13
14 DEFINE_REF(eDVBRegisteredFrontend);
15 DEFINE_REF(eDVBRegisteredDemux);
16
17 DEFINE_REF(eDVBAllocatedFrontend);
18
19 eDVBAllocatedFrontend::eDVBAllocatedFrontend(eDVBRegisteredFrontend *fe): m_fe(fe)
20 {
21         m_fe->inc_use();
22 }
23
24 eDVBAllocatedFrontend::~eDVBAllocatedFrontend()
25 {
26         m_fe->dec_use();
27 }
28
29 DEFINE_REF(eDVBAllocatedDemux);
30
31 eDVBAllocatedDemux::eDVBAllocatedDemux(eDVBRegisteredDemux *demux): m_demux(demux)
32 {
33         m_demux->m_inuse++;
34 }
35
36 eDVBAllocatedDemux::~eDVBAllocatedDemux()
37 {
38         --m_demux->m_inuse;
39 }
40
41 DEFINE_REF(eDVBResourceManager);
42
43 eDVBResourceManager *eDVBResourceManager::instance;
44
45 RESULT eDVBResourceManager::getInstance(ePtr<eDVBResourceManager> &ptr)
46 {
47         if (instance)
48         {
49                 ptr = instance;
50                 return 0;
51         }
52         return -1;
53 }
54
55 ePtr<eDVBResourceManager> NewResourceManagerPtr(void)
56 {
57         ePtr<eDVBResourceManager> ptr;
58         eDVBResourceManager::getInstance(ptr);
59         return ptr;
60 }
61
62 eDVBResourceManager::eDVBResourceManager()
63         :m_releaseCachedChannelTimer(eApp)
64 {
65         avail = 1;
66         busy = 0;
67         m_sec = new eDVBSatelliteEquipmentControl(m_frontend);
68         if (!instance)
69                 instance = this;
70                 
71                 /* search available adapters... */
72
73                 // add linux devices
74         
75         int num_adapter = 0;
76         while (eDVBAdapterLinux::exist(num_adapter))
77         {
78                 addAdapter(new eDVBAdapterLinux(num_adapter));
79                 num_adapter++;
80         }
81         
82         eDebug("found %d adapter, %d frontends and %d demux", 
83                 m_adapter.size(), m_frontend.size(), m_demux.size());
84
85         CONNECT(m_releaseCachedChannelTimer.timeout, eDVBResourceManager::releaseCachedChannel);
86 }
87
88 void eDVBResourceManager::feStateChanged()
89 {
90         int mask=0;
91         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
92                 if (i->m_inuse)
93                         mask |= ( 1 << i->m_frontend->getID() );
94         /* emit */ frontendUseMaskChanged(mask);
95 }
96
97 DEFINE_REF(eDVBAdapterLinux);
98 eDVBAdapterLinux::eDVBAdapterLinux(int nr): m_nr(nr)
99 {
100                 // scan frontends
101         int num_fe = 0;
102         
103         eDebug("scanning for frontends..");
104         while (1)
105         {
106                 struct stat s;
107                 char filename[128];
108 #if HAVE_DVB_API_VERSION < 3
109                 sprintf(filename, "/dev/dvb/card%d/frontend%d", m_nr, num_fe);
110 #else
111                 sprintf(filename, "/dev/dvb/adapter%d/frontend%d", m_nr, num_fe);
112 #endif
113                 if (stat(filename, &s))
114                         break;
115                 ePtr<eDVBFrontend> fe;
116
117                 int ok = 0;
118                 fe = new eDVBFrontend(m_nr, num_fe, ok);
119                 if (ok)
120                         m_frontend.push_back(fe);
121                 ++num_fe;
122         }
123         
124                 // scan demux
125         int num_demux = 0;
126         while (1)
127         {
128                 struct stat s;
129                 char filename[128];
130 #if HAVE_DVB_API_VERSION < 3
131                 sprintf(filename, "/dev/dvb/card%d/demux%d", m_nr, num_demux);
132 #else
133                 sprintf(filename, "/dev/dvb/adapter%d/demux%d", m_nr, num_demux);
134 #endif
135                 if (stat(filename, &s))
136                         break;
137                 ePtr<eDVBDemux> demux;
138                 
139                 demux = new eDVBDemux(m_nr, num_demux);
140                 m_demux.push_back(demux);
141                         
142                 ++num_demux;
143         }
144 }
145
146 int eDVBAdapterLinux::getNumDemux()
147 {
148         return m_demux.size();
149 }
150
151 RESULT eDVBAdapterLinux::getDemux(ePtr<eDVBDemux> &demux, int nr)
152 {
153         eSmartPtrList<eDVBDemux>::iterator i(m_demux.begin());
154         while (nr && (i != m_demux.end()))
155         {
156                 --nr;
157                 ++i;
158         }
159         
160         if (i != m_demux.end())
161                 demux = *i;
162         else
163                 return -1;
164                 
165         return 0;
166 }
167
168 int eDVBAdapterLinux::getNumFrontends()
169 {
170         return m_frontend.size();
171 }
172
173 RESULT eDVBAdapterLinux::getFrontend(ePtr<eDVBFrontend> &fe, int nr)
174 {
175         eSmartPtrList<eDVBFrontend>::iterator i(m_frontend.begin());
176         while (nr && (i != m_frontend.end()))
177         {
178                 --nr;
179                 ++i;
180         }
181         
182         if (i != m_frontend.end())
183                 fe = *i;
184         else
185                 return -1;
186                 
187         return 0;
188 }
189
190 int eDVBAdapterLinux::exist(int nr)
191 {
192         struct stat s;
193         char filename[128];
194 #if HAVE_DVB_API_VERSION < 3
195         sprintf(filename, "/dev/dvb/card%d", nr);
196 #else
197         sprintf(filename, "/dev/dvb/adapter%d", nr);
198 #endif
199         if (!stat(filename, &s))
200                 return 1;
201         return 0;
202 }
203
204 eDVBResourceManager::~eDVBResourceManager()
205 {
206         if (instance == this)
207                 instance = 0;
208 }
209
210 void eDVBResourceManager::addAdapter(iDVBAdapter *adapter)
211 {
212         int num_fe = adapter->getNumFrontends();
213         int num_demux = adapter->getNumDemux();
214         
215         m_adapter.push_back(adapter);
216         
217         int i;
218         for (i=0; i<num_demux; ++i)
219         {
220                 ePtr<eDVBDemux> demux;
221                 if (!adapter->getDemux(demux, i))
222                         m_demux.push_back(new eDVBRegisteredDemux(demux, adapter));
223         }
224
225         ePtr<eDVBRegisteredFrontend> prev_dvbt_frontend;
226         for (i=0; i<num_fe; ++i)
227         {
228                 ePtr<eDVBFrontend> frontend;
229                 if (!adapter->getFrontend(frontend, i))
230                 {
231                         int frontendType=0;
232                         frontend->getFrontendType(frontendType);
233                         eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter);
234                         CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged);
235                         m_frontend.push_back(new_fe);
236                         frontend->setSEC(m_sec);
237                         // we must link all dvb-t frontends ( for active antenna voltage )
238                         if (frontendType == iDVBFrontend::feTerrestrial)
239                         {
240                                 if (prev_dvbt_frontend)
241                                 {
242                                         prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (int)new_fe);
243                                         frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (int)&(*prev_dvbt_frontend));
244                                 }
245                                 prev_dvbt_frontend = new_fe;
246                         }
247                 }
248         }
249 }
250
251 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm)
252 {
253         ePtr<eDVBRegisteredFrontend> best;
254         int bestval = 0;
255
256         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
257                 if (!i->m_inuse)
258                 {
259                         int c = i->m_frontend->isCompatibleWith(feparm);
260                         if (c > bestval)
261                         {
262                                 bestval = c;
263                                 best = i;
264                         }
265                 }
266
267         if (best)
268         {
269                 fe = new eDVBAllocatedFrontend(best);
270                 return 0;
271         }
272         
273         fe = 0;
274         
275         return -1;
276 }
277
278 RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr<eDVBAllocatedFrontend> &fe, int nr)
279 {
280         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i, --nr)
281                 if ((!nr) && !i->m_inuse)
282                 {
283                         fe = new eDVBAllocatedFrontend(i);
284                         return 0;
285                 }
286         
287         fe = 0;
288         return -1;
289 }
290
291 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int cap)
292 {
293                 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
294                    never use the first one unless we need a decoding demux. */
295
296         eDebug("allocate demux");
297         eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
298         
299         if (i == m_demux.end())
300                 return -1;
301                 
302         int n=0;
303                 /* FIXME: hardware demux policy */
304         if (!(cap & iDVBChannel::capDecode))
305         {
306                 if (m_demux.size() > 2)  /* assumed to be true, otherwise we have lost anyway */
307                 {
308                         ++i, ++n;
309                         ++i, ++n;
310                 }
311         }
312         
313         for (; i != m_demux.end(); ++i, ++n)
314         {
315                 int is_decode = n < 2;
316                 
317                 int in_use = is_decode ? (i->m_demux->getRefCount() != 2) : i->m_inuse;
318                 
319                 if ((!in_use) && ((!fe) || (i->m_adapter == fe->m_adapter)))
320                 {
321                         if ((cap & iDVBChannel::capDecode) && !is_decode)
322                                 continue;
323                         
324                         demux = new eDVBAllocatedDemux(i);
325                         if (fe)
326                                 demux->get().setSourceFrontend(fe->m_frontend->getID());
327                         else
328                                 demux->get().setSourcePVR(0);
329                         return 0;
330                 }
331         }
332         eDebug("demux not found");
333         return -1;
334 }
335
336 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
337 {
338         m_list = list;
339         return 0;
340 }
341
342 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
343 {
344         list = m_list;
345         if (list)
346                 return 0;
347         else
348                 return -ENOENT;
349 }
350
351 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel)
352 {
353                 /* first, check if a channel is already existing. */
354
355         if (m_cached_channel)
356         {
357                 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
358                 if(channelid==cache_chan->getChannelID())
359                 {
360                         eDebug("use cached_channel");
361                         channel = m_cached_channel;
362                         return 0;
363                 }
364                 m_cached_channel_state_changed_conn.disconnect();
365                 m_cached_channel=0;
366                 m_releaseCachedChannelTimer.stop();
367         }
368
369 //      eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
370         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
371         {
372 //              eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
373                 if (i->m_channel_id == channelid)
374                 {
375 //                      eDebug("found shared channel..");
376                         channel = i->m_channel;
377                         return 0;
378                 }
379         }
380         
381         /* no currently available channel is tuned to this channelid. create a new one, if possible. */
382
383         if (!m_list)
384         {
385                 eDebug("no channel list set!");
386                 return -ENOENT;
387         }
388
389         ePtr<iDVBFrontendParameters> feparm;
390         if (m_list->getChannelFrontendData(channelid, feparm))
391         {
392                 eDebug("channel not found!");
393                 return -ENOENT;
394         }
395
396         /* allocate a frontend. */
397         
398         ePtr<eDVBAllocatedFrontend> fe;
399         
400         if (allocateFrontend(fe, feparm))
401                 return errNoFrontend;
402
403         RESULT res;
404         ePtr<eDVBChannel> ch;
405         ch = new eDVBChannel(this, fe);
406
407         res = ch->setChannel(channelid, feparm);
408         if (res)
409         {
410                 channel = 0;
411                 return errChidNotFound;
412         }
413         m_cached_channel = channel = ch;
414         m_cached_channel_state_changed_conn =
415                 CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
416
417         return 0;
418 }
419
420 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
421 {
422         int state=0;
423         chan->getState(state);
424         switch (state)
425         {
426                 case iDVBChannel::state_release:
427                 case iDVBChannel::state_ok:
428                 {
429                         eDebug("stop release channel timer");
430                         m_releaseCachedChannelTimer.stop();
431                         break;
432                 }
433                 case iDVBChannel::state_last_instance:
434                 {
435                         eDebug("start release channel timer");
436                         m_releaseCachedChannelTimer.start(3000, true);
437                         break;
438                 }
439                 default: // ignore all other events
440                         break;
441         }
442 }
443
444 void eDVBResourceManager::releaseCachedChannel()
445 {
446         eDebug("release cached channel (timer timeout)");
447         m_cached_channel=0;
448 }
449
450 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int frontend_index)
451 {
452         ePtr<eDVBAllocatedFrontend> fe;
453
454         if (m_cached_channel)
455         {
456                 m_cached_channel_state_changed_conn.disconnect();
457                 m_cached_channel=0;
458                 m_releaseCachedChannelTimer.stop();
459         }
460
461         if (allocateFrontendByIndex(fe, frontend_index))
462                 return errNoFrontend;
463         
464         eDVBChannel *ch;
465         ch = new eDVBChannel(this, fe);
466
467         channel = ch;
468         return 0;
469 }
470
471
472 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
473 {
474         ePtr<eDVBAllocatedDemux> demux;
475
476         if (m_cached_channel && m_releaseCachedChannelTimer.isActive())
477         {
478                 m_cached_channel_state_changed_conn.disconnect();
479                 m_cached_channel=0;
480                 m_releaseCachedChannelTimer.stop();
481         }
482
483         eDVBChannel *ch;
484         ch = new eDVBChannel(this, 0);
485
486         channel = ch;
487         return 0;
488 }
489
490 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
491 {
492         m_active_channels.push_back(active_channel(chid, ch));
493         /* emit */ m_channelAdded(ch);
494         return 0;
495 }
496
497 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
498 {
499         int cnt = 0;
500         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
501         {
502                 if (i->m_channel == ch)
503                 {
504                         i = m_active_channels.erase(i);
505                         ++cnt;
506                 } else
507                         ++i;
508         }
509         ASSERT(cnt == 1);
510         if (cnt == 1)
511                 return 0;
512         return -ENOENT;
513 }
514
515 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
516 {
517         connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
518         return 0;
519 }
520
521 int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm)
522 {
523         ePtr<eDVBRegisteredFrontend> best;
524         int bestval = 0;
525
526         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
527                 if (!i->m_inuse)
528                 {
529                         int c = i->m_frontend->isCompatibleWith(feparm);
530                         if (c > bestval)
531                                 bestval = c;
532                 }
533
534         return bestval;
535 }
536
537 int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore)
538 {
539         int ret=30000;
540         if (m_cached_channel)
541         {
542                 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
543                 if(channelid==cache_chan->getChannelID())
544                         return ret;
545         }
546
547                 /* first, check if a channel is already existing. */
548 //      eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
549         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
550         {
551 //              eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
552                 if (i->m_channel_id == channelid)
553                 {
554 //                      eDebug("found shared channel..");
555                         return ret;
556                 }
557         }
558
559         int *decremented_cached_channel_fe_usecount=NULL,
560                 *decremented_fe_usecount=NULL;
561
562         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
563         {
564 //              eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
565                 if (i->m_channel_id == ignore)
566                 {
567                         eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
568                         // one eUsePtr<iDVBChannel> is used in eDVBServicePMTHandler
569                         // another on eUsePtr<iDVBChannel> is used in the eDVBScan instance used in eDVBServicePMTHandler (for SDT scan)
570                         // so we must check here if usecount is 3 (when the channel is equal to the cached channel)
571                         // or 2 when the cached channel is not equal to the compared channel
572                         if (channel == &(*m_cached_channel) ? channel->getUseCount() == 3 : channel->getUseCount() == 2)  // channel only used once..
573                         {
574                                 ePtr<iDVBFrontend> fe;
575                                 if (!i->m_channel->getFrontend(fe))
576                                 {
577                                         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
578                                         {
579                                                 if ( &(*fe) == &(*ii->m_frontend) )
580                                                 {
581                                                         --ii->m_inuse;
582                                                         decremented_fe_usecount = &ii->m_inuse;
583                                                         if (channel == &(*m_cached_channel))
584                                                                 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
585                                                         break;
586                                                 }
587                                         }
588                                 }
589                         }
590                         break;
591                 }
592         }
593
594         if (!decremented_cached_channel_fe_usecount)
595         {
596                 if (m_cached_channel)
597                 {
598                         eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
599                         if (channel->getUseCount() == 1)
600                         {
601                                 ePtr<iDVBFrontend> fe;
602                                 if (!channel->getFrontend(fe))
603                                 {
604                                         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
605                                         {
606                                                 if ( &(*fe) == &(*ii->m_frontend) )
607                                                 {
608                                                         --ii->m_inuse;
609                                                         decremented_cached_channel_fe_usecount = &ii->m_inuse;
610                                                         break;
611                                                 }
612                                         }
613                                 }
614                         }
615                 }
616         }
617         else
618                 decremented_cached_channel_fe_usecount=NULL;
619
620         ePtr<iDVBFrontendParameters> feparm;
621
622         if (!m_list)
623         {
624                 eDebug("no channel list set!");
625                 ret = 0;
626                 goto error;
627         }
628
629         if (m_list->getChannelFrontendData(channelid, feparm))
630         {
631                 eDebug("channel not found!");
632                 ret = 0;
633                 goto error;
634         }
635
636         ret = canAllocateFrontend(feparm);
637
638 error:
639         if (decremented_fe_usecount)
640                 ++(*decremented_fe_usecount);
641         if (decremented_cached_channel_fe_usecount)
642                 ++(*decremented_cached_channel_fe_usecount);
643
644         return ret;
645 }
646
647 class eDVBChannelFilePush: public eFilePushThread
648 {
649 public:
650         void setIFrameSearch(int enabled) { m_iframe_search = enabled; m_iframe_state = 0; }
651 protected:
652         int m_iframe_search, m_iframe_state, m_pid;
653         int filterRecordData(const unsigned char *data, int len, size_t &current_span_remaining);
654 };
655
656 int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, size_t &current_span_remaining)
657 {
658 #if 0 /* not yet */
659         if (!m_iframe_search)
660                 return len;
661
662         unsigned char *data = (unsigned char*)_data; /* remove that const. we know what we are doing. */
663
664         eDebug("filterRecordData, size=%d (mod 188=%d), first byte is %02x", len, len %188, data[0]);
665
666         unsigned char *d = data;
667         while ((d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3)))
668         {
669                 int offset = d - data;
670                 int ts_offset = offset - offset % 188; /* offset to the start of TS packet */
671                 unsigned char *ts = data + ts_offset;
672                 int pid = ((ts[1] << 8) | ts[2]) & 0x1FFF;
673
674                 if ((d[3] == 0) && (m_pid == pid))  /* picture start */
675                 {
676                         int picture_type = (d[5] >> 3) & 7;
677                         d += 4;
678                         
679                         eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid);
680
681                         if (m_iframe_state == 1)
682                         {
683                                         /* we are allowing data, and stop allowing data on the next frame. 
684                                            we now found a frame. so stop here. */
685                                 memset(data + offset, 0, 188 - (offset%188)); /* zero out rest of TS packet */
686                                 current_span_remaining = 0;
687                                 m_iframe_state = 0;
688                                 unsigned char *fts = ts + 188;
689                                 while (fts < (data + len))
690                                 {
691                                         fts[1] |= 0x1f;
692                                         fts[2] |= 0xff; /* drop packet */
693                                         fts += 188;
694                                 }
695
696                                 return len; // ts_offset + 188; /* deliver this packet, but not more. */
697                         } else
698                         {
699                                 if (picture_type != 1) /* we are only interested in I frames */
700                                         continue;
701                         
702                                 unsigned char *fts = data;
703                                 while (fts < ts)
704                                 {
705                                         fts[1] |= 0x1f;
706                                         fts[2] |= 0xff; /* drop packet */
707                                 
708                                         fts += 188;
709                                 }
710                                                 /* force payload only */
711                                 ts[3] &= ~0x30;
712                                 ts[3] |=  0x10;
713                                 
714 //                              memset(ts + 4, 0xFF, (offset % 188) - 4);
715
716                                 m_iframe_state = 1;
717                         }
718                 } else if ((d[3] & 0xF0) == 0xE0) /* video stream */
719                 {
720                         if (m_pid != pid)
721                         {
722                                 eDebug("now locked to pid %04x", pid);
723                                 m_pid = pid;
724                         }
725 //                      m_pid = 0x6e;
726                         d += 4;
727                 } else
728                         d += 4; /* ignore */
729
730         }
731
732         if (m_iframe_state == 1)
733                 return len;
734         else
735                 return 0; /* we need find an iframe first */
736 #else
737         return len;
738 #endif
739 }
740
741 DEFINE_REF(eDVBChannel);
742
743 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
744 {
745         m_frontend = frontend;
746
747         m_pvr_thread = 0;
748         
749         m_skipmode_n = m_skipmode_m = 0;
750         
751         if (m_frontend)
752                 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
753 }
754
755 eDVBChannel::~eDVBChannel()
756 {
757         if (m_channel_id)
758                 m_mgr->removeChannel(this);
759
760         stopFile();
761 }
762
763 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
764 {
765         int state, ourstate = 0;
766         
767                 /* if we are already in shutdown, don't change state. */
768         if (m_state == state_release)
769                 return;
770         
771         if (fe->getState(state))
772                 return;
773         
774         if (state == iDVBFrontend::stateLock)
775         {
776                 eDebug("OURSTATE: ok");
777                 ourstate = state_ok;
778         } else if (state == iDVBFrontend::stateTuning)
779         {
780                 eDebug("OURSTATE: tuning");
781                 ourstate = state_tuning;
782         } else if (state == iDVBFrontend::stateLostLock)
783         {
784                         /* on managed channels, we try to retune in order to re-acquire lock. */
785                 if (m_current_frontend_parameters)
786                 {
787                         eDebug("OURSTATE: lost lock, trying to retune");
788                         ourstate = state_tuning;
789                         m_frontend->get().tune(*m_current_frontend_parameters);
790                 } else
791                         /* on unmanaged channels, we don't do this. the client will do this. */
792                 {
793                         eDebug("OURSTATE: lost lock, unavailable now.");
794                         ourstate = state_unavailable;
795                 }
796         } else if (state == iDVBFrontend::stateFailed)
797         {
798                 eDebug("OURSTATE: failed");
799                 ourstate = state_failed;
800         } else
801                 eFatal("state unknown");
802         
803         if (ourstate != m_state)
804         {
805                 m_state = ourstate;
806                 m_stateChanged(this);
807         }
808 }
809
810 void eDVBChannel::pvrEvent(int event)
811 {
812         switch (event)
813         {
814         case eFilePushThread::evtEOF:
815                 eDebug("eDVBChannel: End of file!");
816                 m_event(this, evtEOF);
817                 break;
818         case eFilePushThread::evtUser: /* start */
819                 eDebug("SOF");
820                 m_event(this, evtSOF);
821                 break;
822         }
823 }
824
825 void eDVBChannel::cueSheetEvent(int event)
826 {
827         switch (event)
828         {
829         case eCueSheet::evtSeek:
830                 eDebug("seek.");
831                 flushPVR(m_cue->m_decoding_demux);
832                 break;
833         case eCueSheet::evtSkipmode:
834         {
835                 {
836                         eSingleLocker l(m_cue->m_lock);
837                         m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
838                         if (m_cue->m_skipmode_ratio)
839                         {
840                                 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
841                                 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
842                                                 /* i agree that this might look a bit like black magic. */
843                                 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
844                                 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
845                                 
846                                 if (m_cue->m_skipmode_ratio < 0)
847                                         m_skipmode_m -= m_skipmode_n;
848         
849                                 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
850                                 
851                                 if (abs(m_skipmode_m) < abs(m_skipmode_n))
852                                 {
853                                         eWarning("something is wrong with this calculation");
854                                         m_skipmode_n = m_skipmode_m = 0;
855                                 }
856                                 
857                         } else
858                         {
859                                 eDebug("skipmode ratio is 0, normal play");
860                                 m_skipmode_n = m_skipmode_m = 0;
861                         }
862                 }
863                 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
864                 eDebug("flush pvr");
865                 flushPVR(m_cue->m_decoding_demux);
866                 eDebug("done");
867                 break;
868         }
869         case eCueSheet::evtSpanChanged:
870         {
871                 m_source_span.clear();
872                 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
873                 {
874                         off_t offset_in, offset_out;
875                         pts_t pts_in = i->first, pts_out = i->second;
876                         if (m_tstools.getOffset(offset_in, pts_in) || m_tstools.getOffset(offset_out, pts_out))
877                         {
878                                 eDebug("span translation failed.\n");
879                                 continue;
880                         }
881                         eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
882                         m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
883                 }
884                 break;
885         }
886         }
887 }
888
889         /* align toward zero */
890 static inline long long align(long long x, int align)
891 {
892         int sign = x < 0;
893
894         if (sign)
895                 x = -x;
896
897         x -= x % align;
898
899         if (sign)
900                 x = -x;
901
902         return x;
903 }
904
905         /* remember, this gets called from another thread. */
906 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
907 {
908         const int blocksize = 188;
909         unsigned int max = align(10*1024*1024, blocksize);
910         current_offset = align(current_offset, blocksize);
911         
912         if (!m_cue)
913         {
914                 eDebug("no cue sheet. forcing normal play");
915                 start = current_offset;
916                 size = max;
917                 return;
918         }
919
920         eSingleLocker l(m_cue->m_lock);
921         
922         if (!m_cue->m_decoding_demux)
923         {
924                 start = current_offset;
925                 size = max;
926                 eDebug("getNextSourceSpan, no decoding demux. forcing normal play");
927                 return;
928         }
929
930         if (m_skipmode_n)
931         {
932                 eDebug("skipmode %d:%d", m_skipmode_m, m_skipmode_n);
933                 max = align(m_skipmode_n, blocksize);
934         }
935
936         eDebug("getNextSourceSpan, current offset is %08llx, m_skipmode_m = %d!", current_offset, m_skipmode_m);
937
938         current_offset += align(m_skipmode_m, blocksize);
939
940         while (!m_cue->m_seek_requests.empty())
941         {
942                 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
943                 m_cue->m_seek_requests.pop_front();
944                 int relative = seek.first;
945                 pts_t pts = seek.second;
946
947                 pts_t now = 0;
948                 if (relative)
949                 {
950                         if (!m_cue->m_decoder)
951                         {
952                                 eDebug("no decoder - can't seek relative");
953                                 continue;
954                         }
955                         if (m_cue->m_decoder->getPTS(0, now))
956                         {
957                                 eDebug("decoder getPTS failed, can't seek relative");
958                                 continue;
959                         }
960                         if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
961                         {
962                                 eDebug("seekTo: getCurrentPosition failed!");
963                                 continue;
964                         }
965                 } else if (pts < 0) /* seek relative to end */
966                 {
967                         pts_t len;
968                         if (!getLength(len))
969                         {
970                                 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
971                                 pts += len;
972                         } else
973                         {
974                                 eWarning("getLength failed - can't seek relative to end!");
975                                 continue;
976                         }
977                 }
978                 
979                 if (relative == 1) /* pts relative */
980                 {
981                         pts += now;
982                         if (pts < 0)
983                                 pts = 0;
984                 }
985
986                 if (relative != 2)
987                         if (pts < 0)
988                                 pts = 0;
989                 
990                 if (relative == 2) /* AP relative */
991                 {
992                         eDebug("AP relative seeking: %lld, at %lld", pts, now);
993                         pts_t nextap;
994                         if (m_tstools.getNextAccessPoint(nextap, now, pts))
995                         {
996                                 pts = now;
997                                 eDebug("AP relative seeking failed!");
998                         } else
999                         {
1000                                 eDebug("next ap is %llx\n", pts);
1001                                 pts = nextap;
1002                         }
1003                 }
1004                 
1005                 off_t offset = 0;
1006                 if (m_tstools.getOffset(offset, pts))
1007                 {
1008                         eDebug("get offset for pts=%lld failed!", pts);
1009                         continue;
1010                 }
1011
1012                 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1013                 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1014         }
1015
1016         for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1017         {
1018                 long long aligned_start = align(i->first, blocksize);
1019                 long long aligned_end = align(i->second, blocksize);
1020         
1021                 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1022                 {
1023                         start = current_offset;
1024                                 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1025                         if ((aligned_end - current_offset) > max)
1026                                 size = max;
1027                         else
1028                                 size = aligned_end - current_offset;
1029                         eDebug("HIT, %lld < %lld < %lld, size: %d", i->first, current_offset, i->second, size);
1030                         return;
1031                 }
1032                 if (current_offset < aligned_start)
1033                 {
1034                                 /* ok, our current offset is in an 'out' zone. */
1035                         if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1036                         {
1037                                         /* in normal playback, just start at the next zone. */
1038                                 start = i->first;
1039                                 
1040                                         /* size is not 64bit! */
1041                                 if ((i->second - i->first) > max)
1042                                         size = max;
1043                                 else
1044                                         size = aligned_end - aligned_start;
1045
1046                                 eDebug("skip");
1047                                 if (m_skipmode_m < 0)
1048                                 {
1049                                         eDebug("reached SOF");
1050                                                 /* reached SOF */
1051                                         m_skipmode_m = 0;
1052                                         m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1053                                 }
1054                         } else
1055                         {
1056                                         /* when skipping reverse, however, choose the zone before. */
1057                                 --i;
1058                                 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1059                                 size_t len;
1060                                 
1061                                 if ((i->second - i->first) > max)
1062                                         len = max;
1063                                 else
1064                                         len = aligned_end - aligned_start;
1065
1066                                 start = aligned_end - len;
1067                                 eDebug("skipping to %llx, %d", start, len);
1068                         }
1069                         
1070                         eDebug("result: %llx, %x (%llx %llx)", start, size, aligned_start, aligned_end);
1071                         return;
1072                 }
1073         }
1074         
1075         if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1076         {
1077                 eDebug("reached SOF");
1078                 m_skipmode_m = 0;
1079                 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1080         }
1081         
1082         start = current_offset;
1083         size = max;
1084
1085         eDebug("END OF CUESHEET. (%08llx, %d)", start, size);
1086         return;
1087 }
1088
1089 void eDVBChannel::AddUse()
1090 {
1091         if (++m_use_count > 1 && m_state == state_last_instance)
1092         {
1093                 m_state = state_ok;
1094                 m_stateChanged(this);
1095         }
1096 }
1097
1098 void eDVBChannel::ReleaseUse()
1099 {
1100         if (!--m_use_count)
1101         {
1102                 m_state = state_release;
1103                 m_stateChanged(this);
1104         }
1105         else if (m_use_count == 1)
1106         {
1107                 m_state = state_last_instance;
1108                 m_stateChanged(this);
1109         }
1110 }
1111
1112 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1113 {
1114         if (m_channel_id)
1115                 m_mgr->removeChannel(this);
1116                 
1117         if (!channelid)
1118                 return 0;
1119
1120         if (!m_frontend)
1121         {
1122                 eDebug("no frontend to tune!");
1123                 return -ENODEV;
1124         }
1125         
1126         m_channel_id = channelid;
1127         m_mgr->addChannel(channelid, this);
1128         m_state = state_tuning;
1129                         /* if tuning fails, shutdown the channel immediately. */
1130         int res;
1131         res = m_frontend->get().tune(*feparm);
1132         m_current_frontend_parameters = feparm;
1133         
1134         if (res)
1135         {
1136                 m_state = state_release;
1137                 m_stateChanged(this);
1138                 return res;
1139         }
1140         
1141         return 0;
1142 }
1143
1144 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1145 {
1146         connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1147         return 0;
1148 }
1149
1150 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1151 {
1152         connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1153         return 0;
1154 }
1155
1156 RESULT eDVBChannel::getState(int &state)
1157 {
1158         state = m_state;
1159         return 0;
1160 }
1161
1162 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1163 {
1164         return -1;
1165 }
1166
1167 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1168 {
1169         ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1170         
1171         if (!our_demux)
1172         {
1173                 demux = 0;
1174                 
1175                 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1176                         return -1;
1177         }
1178         
1179         demux = *our_demux;
1180                 /* don't hold a reference to the decoding demux, we don't need it. */
1181                 
1182                 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1183                    the refcount is lost. thus, decoding demuxes are never allocated. 
1184                    
1185                    this poses a big problem for PiP. */
1186         if (cap & capDecode)
1187                 our_demux = 0;
1188         return 0;
1189 }
1190
1191 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1192 {
1193         frontend = 0;
1194         if (!m_frontend)
1195                 return -ENODEV;
1196         frontend = &m_frontend->get();
1197         if (frontend)
1198                 return 0;
1199         return -ENODEV;
1200 }
1201
1202 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> &param)
1203 {
1204         param = m_current_frontend_parameters;
1205         return 0;
1206 }
1207
1208 RESULT eDVBChannel::playFile(const char *file)
1209 {
1210         ASSERT(!m_frontend);
1211         if (m_pvr_thread)
1212         {
1213                 m_pvr_thread->stop();
1214                 delete m_pvr_thread;
1215                 m_pvr_thread = 0;
1216         }
1217         
1218         m_tstools.openFile(file);
1219         
1220                 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1221                    THEN DO A REAL FIX HERE! */
1222         
1223                 /* (this codepath needs to be improved anyway.) */
1224 #if HAVE_DVB_API_VERSION < 3
1225         m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1226 #else
1227         m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
1228 #endif
1229         if (m_pvr_fd_dst < 0)
1230         {
1231                 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1232                 return -ENODEV;
1233         }
1234
1235         m_pvr_thread = new eDVBChannelFilePush();
1236         m_pvr_thread->enablePVRCommit(1);
1237         m_pvr_thread->setStreamMode(1);
1238         m_pvr_thread->setScatterGather(this);
1239
1240         if (m_pvr_thread->start(file, m_pvr_fd_dst))
1241         {
1242                 delete m_pvr_thread;
1243                 m_pvr_thread = 0;
1244                 eDebug("can't open PVR file %s (%m)", file);
1245                 return -ENOENT;
1246         }
1247         CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1248
1249         m_state = state_ok;
1250         m_stateChanged(this);
1251
1252         return 0;
1253 }
1254
1255 void eDVBChannel::stopFile()
1256 {
1257         if (m_pvr_thread)
1258         {
1259                 m_pvr_thread->stop();
1260                 ::close(m_pvr_fd_dst);
1261                 delete m_pvr_thread;
1262                 m_pvr_thread = 0;
1263         }
1264 }
1265
1266 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1267 {
1268         m_conn_cueSheetEvent = 0;
1269         m_cue = cuesheet;
1270         if (m_cue)
1271                 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1272 }
1273
1274 RESULT eDVBChannel::getLength(pts_t &len)
1275 {
1276         return m_tstools.calcLen(len);
1277 }
1278
1279 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1280 {
1281         if (!decoding_demux)
1282                 return -1;
1283         
1284         pts_t now;
1285         
1286         int r;
1287         
1288         if (mode == 0) /* demux */
1289         {
1290                 r = decoding_demux->getSTC(now, 0);
1291                 if (r)
1292                 {
1293                         eDebug("demux getSTC failed");
1294                         return -1;
1295                 }
1296         } else
1297                 now = pos; /* fixup supplied */
1298         
1299         off_t off = 0; /* TODO: fixme */
1300         r = m_tstools.fixupPTS(off, now);
1301         if (r)
1302         {
1303                 eDebug("fixup PTS failed");
1304                 return -1;
1305         }
1306         
1307         pos = now;
1308         
1309         return 0;
1310 }
1311
1312 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1313 {
1314                         /* when seeking, we have to ensure that all buffers are flushed.
1315                            there are basically 3 buffers:
1316                            a.) the filepush's internal buffer
1317                            b.) the PVR buffer (before demux)
1318                            c.) the ratebuffer (after demux)
1319                            
1320                            it's important to clear them in the correct order, otherwise
1321                            the ratebuffer (for example) would immediately refill from
1322                            the not-yet-flushed PVR buffer.
1323                         */
1324
1325         m_pvr_thread->pause();
1326                 /* flush internal filepush buffer */
1327         m_pvr_thread->flush();
1328                 /* HACK: flush PVR buffer */
1329         ::ioctl(m_pvr_fd_dst, 0);
1330         
1331                 /* flush ratebuffers (video, audio) */
1332         if (decoding_demux)
1333                 decoding_demux->flush();
1334
1335                 /* demux will also flush all decoder.. */
1336                 /* resume will re-query the SG */
1337         m_pvr_thread->resume();
1338 }
1339
1340 DEFINE_REF(eCueSheet);
1341
1342 eCueSheet::eCueSheet()
1343 {
1344         m_skipmode_ratio = 0;
1345 }
1346
1347 void eCueSheet::seekTo(int relative, const pts_t &pts)
1348 {
1349         {
1350                 eSingleLocker l(m_lock);
1351                 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1352         }
1353         m_event(evtSeek);
1354 }
1355         
1356 void eCueSheet::clear()
1357 {
1358         eSingleLocker l(m_lock);
1359         m_spans.clear();
1360 }
1361
1362 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1363 {
1364         {
1365                 eSingleLocker l(m_lock);
1366                 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1367         }
1368 }
1369
1370 void eCueSheet::commitSpans()
1371 {
1372         m_event(evtSpanChanged);
1373 }
1374
1375 void eCueSheet::setSkipmode(const pts_t &ratio)
1376 {
1377         {
1378                 eSingleLocker l(m_lock);
1379                 m_skipmode_ratio = ratio;
1380         }
1381         m_event(evtSkipmode);
1382 }
1383
1384 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1385 {
1386         m_decoding_demux = demux;
1387         m_decoder = decoder;
1388 }
1389
1390 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1391 {
1392         connection = new eConnection(this, m_event.connect(event));
1393         return 0;
1394 }