aa7958126f2a707e3ccbe4279ee7b45f40de4306
[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->m_inuse++;
22 }
23
24 eDVBAllocatedFrontend::~eDVBAllocatedFrontend()
25 {
26         --m_fe->m_inuse;
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 eDVBResourceManager::eDVBResourceManager()
46 {
47         avail = 1;
48         busy = 0;
49         m_sec = new eDVBSatelliteEquipmentControl(m_frontend);
50         if (!instance)
51                 instance = this;
52                 
53                 /* search available adapters... */
54
55                 // add linux devices
56         
57         int num_adapter = 0;
58         while (eDVBAdapterLinux::exist(num_adapter))
59         {
60                 addAdapter(new eDVBAdapterLinux(num_adapter));
61                 num_adapter++;
62         }
63         
64         eDebug("found %d adapter, %d frontends and %d demux", 
65                 m_adapter.size(), m_frontend.size(), m_demux.size());
66 }
67
68
69 DEFINE_REF(eDVBAdapterLinux);
70 eDVBAdapterLinux::eDVBAdapterLinux(int nr): m_nr(nr)
71 {
72                 // scan frontends
73         int num_fe = 0;
74         
75         eDebug("scanning for frontends..");
76         while (1)
77         {
78                 struct stat s;
79                 char filename[128];
80 #if HAVE_DVB_API_VERSION < 3
81                 sprintf(filename, "/dev/dvb/card%d/frontend%d", m_nr, num_fe);
82 #else
83                 sprintf(filename, "/dev/dvb/adapter%d/frontend%d", m_nr, num_fe);
84 #endif
85                 if (stat(filename, &s))
86                         break;
87                 ePtr<eDVBFrontend> fe;
88
89                 int ok = 0;
90                 fe = new eDVBFrontend(m_nr, num_fe, ok);
91                 if (ok)
92                         m_frontend.push_back(fe);
93                 ++num_fe;
94         }
95         
96                 // scan demux
97         int num_demux = 0;
98         while (1)
99         {
100                 struct stat s;
101                 char filename[128];
102 #if HAVE_DVB_API_VERSION < 3
103                 sprintf(filename, "/dev/dvb/card%d/demux%d", m_nr, num_demux);
104 #else
105                 sprintf(filename, "/dev/dvb/adapter%d/demux%d", m_nr, num_demux);
106 #endif
107                 if (stat(filename, &s))
108                         break;
109                 ePtr<eDVBDemux> demux;
110                 
111                 demux = new eDVBDemux(m_nr, num_demux);
112                 m_demux.push_back(demux);
113                         
114                 ++num_demux;
115         }
116 }
117
118 int eDVBAdapterLinux::getNumDemux()
119 {
120         return m_demux.size();
121 }
122
123 RESULT eDVBAdapterLinux::getDemux(ePtr<eDVBDemux> &demux, int nr)
124 {
125         eSmartPtrList<eDVBDemux>::iterator i(m_demux.begin());
126         while (nr && (i != m_demux.end()))
127         {
128                 --nr;
129                 ++i;
130         }
131         
132         if (i != m_demux.end())
133                 demux = *i;
134         else
135                 return -1;
136                 
137         return 0;
138 }
139
140 int eDVBAdapterLinux::getNumFrontends()
141 {
142         return m_frontend.size();
143 }
144
145 RESULT eDVBAdapterLinux::getFrontend(ePtr<eDVBFrontend> &fe, int nr)
146 {
147         eSmartPtrList<eDVBFrontend>::iterator i(m_frontend.begin());
148         while (nr && (i != m_frontend.end()))
149         {
150                 --nr;
151                 ++i;
152         }
153         
154         if (i != m_frontend.end())
155                 fe = *i;
156         else
157                 return -1;
158                 
159         return 0;
160 }
161
162 int eDVBAdapterLinux::exist(int nr)
163 {
164         struct stat s;
165         char filename[128];
166 #if HAVE_DVB_API_VERSION < 3
167         sprintf(filename, "/dev/dvb/card%d", nr);
168 #else
169         sprintf(filename, "/dev/dvb/adapter%d", nr);
170 #endif
171         if (!stat(filename, &s))
172                 return 1;
173         return 0;
174 }
175
176 eDVBResourceManager::~eDVBResourceManager()
177 {
178         if (instance == this)
179                 instance = 0;
180 }
181
182 void eDVBResourceManager::addAdapter(iDVBAdapter *adapter)
183 {
184         int num_fe = adapter->getNumFrontends();
185         int num_demux = adapter->getNumDemux();
186         
187         m_adapter.push_back(adapter);
188         
189         int i;
190         for (i=0; i<num_demux; ++i)
191         {
192                 ePtr<eDVBDemux> demux;
193                 if (!adapter->getDemux(demux, i))
194                         m_demux.push_back(new eDVBRegisteredDemux(demux, adapter));
195         }
196
197         for (i=0; i<num_fe; ++i)
198         {
199                 ePtr<eDVBFrontend> frontend;
200
201                 if (!adapter->getFrontend(frontend, i))
202                 {
203                         frontend->setTone(iDVBFrontend::toneOff);
204                         frontend->setVoltage(iDVBFrontend::voltageOff);
205                         frontend->setSEC(m_sec);
206                         m_frontend.push_back(new eDVBRegisteredFrontend(frontend, adapter));
207                 }
208         }
209 }
210
211 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm)
212 {
213         ePtr<eDVBRegisteredFrontend> best;
214         int bestval = 0;
215
216         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
217                 if (!i->m_inuse)
218                 {
219                         int c = i->m_frontend->isCompatibleWith(feparm);
220                         if (c > bestval)
221                         {
222                                 bestval = c;
223                                 best = i;
224                         }
225                 }
226
227         if (best)
228         {
229                 fe = new eDVBAllocatedFrontend(best);
230                 return 0;
231         }
232         
233         fe = 0;
234         
235         return -1;
236 }
237
238 RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr<eDVBAllocatedFrontend> &fe, int nr)
239 {
240         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i, --nr)
241                 if ((!nr) && !i->m_inuse)
242                 {
243                         fe = new eDVBAllocatedFrontend(i);
244                         return 0;
245                 }
246         
247         fe = 0;
248         return -1;
249 }
250
251 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int cap)
252 {
253                 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
254                    never use the first one unless we need a decoding demux. */
255
256         eDebug("allocate demux");
257         eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
258         
259         if (i == m_demux.end())
260                 return -1;
261                 
262         int n=0;
263                 /* FIXME: hardware demux policy */
264         if (!(cap & iDVBChannel::capDecode))
265                 ++i, ++n;
266         
267         for (; i != m_demux.end(); ++i, ++n)
268                 if ((!i->m_inuse) && ((!fe) || (i->m_adapter == fe->m_adapter)))
269                 {
270                         if ((cap & iDVBChannel::capDecode) && n)
271                                 continue;
272                         
273                         demux = new eDVBAllocatedDemux(i);
274                         if (fe)
275                                 demux->get().setSourceFrontend(fe->m_frontend->getID());
276                         else
277                                 demux->get().setSourcePVR(0);
278                         return 0;
279                 }
280         eDebug("demux not found");
281         return -1;
282 }
283
284 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
285 {
286         m_list = list;
287         return 0;
288 }
289
290 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
291 {
292         list = m_list;
293         if (list)
294                 return 0;
295         else
296                 return -ENOENT;
297 }
298
299 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel)
300 {
301                 /* first, check if a channel is already existing. */
302         
303 //      eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
304         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
305         {
306 //              eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
307                 if (i->m_channel_id == channelid)
308                 {
309 //                      eDebug("found shared channel..");
310                         channel = i->m_channel;
311                         return 0;
312                 }
313         }
314         
315         /* no currently available channel is tuned to this channelid. create a new one, if possible. */
316
317         if (!m_list)
318         {
319                 eDebug("no channel list set!");
320                 return -ENOENT;
321         }
322
323         ePtr<iDVBFrontendParameters> feparm;
324         if (m_list->getChannelFrontendData(channelid, feparm))
325         {
326                 eDebug("channel not found!");
327                 return -ENOENT;
328         }
329
330         /* allocate a frontend. */
331         
332         ePtr<eDVBAllocatedFrontend> fe;
333         
334         if (allocateFrontend(fe, feparm))
335                 return errNoFrontend;
336
337         RESULT res;
338         ePtr<eDVBChannel> ch;
339         ch = new eDVBChannel(this, fe);
340
341         res = ch->setChannel(channelid, feparm);
342         if (res)
343         {
344                 channel = 0;
345                 return errChidNotFound;
346         }
347         channel = ch;
348
349         return 0;
350 }
351
352 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int frontend_index)
353 {
354         ePtr<eDVBAllocatedFrontend> fe;
355
356         if (allocateFrontendByIndex(fe, frontend_index))
357                 return errNoFrontend;
358         
359         eDVBChannel *ch;
360         ch = new eDVBChannel(this, fe);
361
362         channel = ch;
363         return 0;
364 }
365
366
367 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
368 {
369         ePtr<eDVBAllocatedDemux> demux;
370         
371         eDVBChannel *ch;
372         ch = new eDVBChannel(this, 0);
373         
374         channel = ch;
375         return 0;
376 }
377
378 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
379 {
380         m_active_channels.push_back(active_channel(chid, ch));
381         /* emit */ m_channelAdded(ch);
382         return 0;
383 }
384
385 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
386 {
387         int cnt = 0;
388         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
389         {
390                 if (i->m_channel == ch)
391                 {
392                         i = m_active_channels.erase(i);
393                         ++cnt;
394                 } else
395                         ++i;
396         }
397         ASSERT(cnt == 1);
398         if (cnt == 1)
399                 return 0;
400         return -ENOENT;
401 }
402
403 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
404 {
405         connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
406         return 0;
407 }
408
409 bool eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm)
410 {
411         ePtr<eDVBRegisteredFrontend> best;
412         int bestval = 0;
413
414         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
415                 if (!i->m_inuse)
416                 {
417                         int c = i->m_frontend->isCompatibleWith(feparm);
418                         if (c > bestval)
419                                 bestval = c;
420                 }
421
422         return bestval>0;
423 }
424
425 bool eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore)
426 {
427                 /* first, check if a channel is already existing. */
428 //      eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
429         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
430         {
431 //              eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
432                 if (i->m_channel_id == channelid)
433                 {
434 //                      eDebug("found shared channel..");
435                         return true;
436                 }
437         }
438
439         int *decremented_fe_usecount=NULL;
440
441         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
442         {
443 //              eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
444                 if (i->m_channel_id == ignore)
445                 {
446                         eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
447                         if (channel->getUseCount() == 1)  // channel only used once..
448                         {
449                                 ePtr<iDVBFrontend> fe;
450                                 if (!i->m_channel->getFrontend(fe))
451                                 {
452                                         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
453                                         {
454                                                 if ( &(*fe) == &(*ii->m_frontend) )
455                                                 {
456                                                         --ii->m_inuse;
457                                                         decremented_fe_usecount = &ii->m_inuse;
458                                                         break;
459                                                 }
460                                         }
461                                 }
462                         }
463                         break;
464                 }
465         }
466
467         if (!m_list)
468         {
469                 eDebug("no channel list set!");
470                 return false;
471         }
472
473         ePtr<iDVBFrontendParameters> feparm;
474         if (m_list->getChannelFrontendData(channelid, feparm))
475         {
476                 eDebug("channel not found!");
477                 return false;
478         }
479
480         bool ret = canAllocateFrontend(feparm);
481
482         if (decremented_fe_usecount)
483                 ++(*decremented_fe_usecount);
484
485         return ret;
486 }
487
488 DEFINE_REF(eDVBChannel);
489
490 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
491 {
492         m_frontend = frontend;
493
494         m_pvr_thread = 0;
495         
496         if (m_frontend)
497                 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
498 }
499
500 eDVBChannel::~eDVBChannel()
501 {
502         if (m_channel_id)
503                 m_mgr->removeChannel(this);
504         
505         if (m_pvr_thread)
506         {
507                 m_pvr_thread->stop();
508                 ::close(m_pvr_fd_src);
509                 ::close(m_pvr_fd_dst);
510                 delete m_pvr_thread;
511         }
512 }
513
514 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
515 {
516         int state, ourstate = 0;
517         
518                 /* if we are already in shutdown, don't change state. */
519         if (m_state == state_release)
520                 return;
521         
522         if (fe->getState(state))
523                 return;
524         
525         if (state == iDVBFrontend::stateLock)
526         {
527                 eDebug("OURSTATE: ok");
528                 ourstate = state_ok;
529         } else if (state == iDVBFrontend::stateTuning)
530         {
531                 eDebug("OURSTATE: tuning");
532                 ourstate = state_tuning;
533         } else if (state == iDVBFrontend::stateLostLock)
534         {
535                 eDebug("OURSTATE: lost lock");
536                 ourstate = state_unavailable;
537         } else if (state == iDVBFrontend::stateFailed)
538         {
539                 eDebug("OURSTATE: failed");
540                 ourstate = state_failed;
541         } else
542                 eFatal("state unknown");
543         
544         if (ourstate != m_state)
545         {
546                 m_state = ourstate;
547                 m_stateChanged(this);
548         }
549 }
550
551 void eDVBChannel::AddUse()
552 {
553         ++m_use_count;
554 }
555
556 void eDVBChannel::ReleaseUse()
557 {
558         if (!--m_use_count)
559         {
560                 m_state = state_release;
561                 m_stateChanged(this);
562         }
563 }
564
565 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
566 {
567         if (m_channel_id)
568                 m_mgr->removeChannel(this);
569                 
570         if (!channelid)
571                 return 0;
572
573         if (!m_frontend)
574         {
575                 eDebug("no frontend to tune!");
576                 return -ENODEV;
577         }
578         
579         m_channel_id = channelid;
580         m_mgr->addChannel(channelid, this);
581         m_state = state_tuning;
582                         /* if tuning fails, shutdown the channel immediately. */
583         int res;
584         res = m_frontend->get().tune(*feparm);
585         
586         if (res)
587         {
588                 m_state = state_release;
589                 m_stateChanged(this);
590                 return res;
591         }
592         
593         return 0;
594 }
595
596 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
597 {
598         connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
599         return 0;
600 }
601
602 RESULT eDVBChannel::getState(int &state)
603 {
604         state = m_state;
605         return 0;
606 }
607
608 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
609 {
610         return -1;
611 }
612
613 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
614 {
615         eDebug("get %d demux", cap);
616         ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
617         
618         if (!our_demux)
619         {
620                 demux = 0;
621                 
622                 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
623                         return -1;
624                 
625         }
626         
627         demux = *our_demux;
628         if (cap & capDecode)
629         {
630                 our_demux = 0;
631         }
632         return 0;
633 }
634
635 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
636 {
637         frontend = &m_frontend->get();
638         if (frontend)
639                 return 0;
640         else
641                 return -ENODEV;
642 }
643
644 RESULT eDVBChannel::playFile(const char *file)
645 {
646         ASSERT(!m_frontend);
647         if (m_pvr_thread)
648         {
649                 m_pvr_thread->stop();
650                 delete m_pvr_thread;
651                 m_pvr_thread = 0;
652         }
653         
654         m_tstools.openFile(file);
655         
656                 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
657                    THEN DO A REAL FIX HERE! */
658         
659                 /* (this codepath needs to be improved anyway.) */
660         m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
661         if (m_pvr_fd_dst < 0)
662         {
663                 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
664                 return -ENODEV;
665         }
666         
667         m_pvr_fd_src = open(file, O_RDONLY);
668         if (m_pvr_fd_src < 0)
669         {
670                 eDebug("can't open PVR m_pvr_fd_src file %s (%m)", file);
671                 close(m_pvr_fd_dst);
672                 return -ENOENT;
673         }
674         
675         m_state = state_ok;
676         m_stateChanged(this);
677         
678         m_pvr_thread = new eFilePushThread();
679         m_pvr_thread->start(m_pvr_fd_src, m_pvr_fd_dst);
680
681         return 0;
682 }
683
684 RESULT eDVBChannel::getLength(pts_t &len)
685 {
686         return m_tstools.calcLen(len);
687 }
688
689 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos)
690 {
691         if (!decoding_demux)
692                 return -1;
693         
694         off_t begin = 0;
695                 /* getPTS for offset 0 is cached, so it doesn't harm. */
696         int r = m_tstools.getPTS(begin, pos);
697         if (r)
698         {
699                 eDebug("tstools getpts(0) failed!");
700                 return r;
701         }
702         
703         pts_t now;
704         
705         r = decoding_demux->getSTC(now);
706
707         if (r)
708         {
709                 eDebug("demux getSTC failed");
710                 return -1;
711         }
712         
713 //      eDebug("STC: %08llx PTS: %08llx, diff %lld", now, pos, now - pos);
714                 /* when we are less than 10 seconds before the start, return 0. */
715                 /* (we're just waiting for the timespam to start) */
716         if ((now < pos) && ((pos - now) < 90000 * 10))
717         {
718                 pos = 0;
719                 return 0;
720         }
721         
722         if (now < pos) /* wrap around */
723                 pos = now + ((pts_t)1)<<33 - pos;
724         else
725                 pos = now - pos;
726         
727         return 0;
728 }
729
730 RESULT eDVBChannel::seekTo(iDVBDemux *decoding_demux, int relative, pts_t &pts)
731 {
732         int bitrate = m_tstools.calcBitrate(); /* in bits/s */
733         
734         if (bitrate == -1)
735                 return -1;
736         
737         if (relative)
738         {
739                 pts_t now;
740                 if (getCurrentPosition(decoding_demux, now))
741                 {
742                         eDebug("seekTo: getCurrentPosition failed!");
743                         return -1;
744                 }
745                 pts += now;
746         }
747         
748         if (pts < 0)
749                 pts = 0;
750         
751         off_t offset = (pts * (pts_t)bitrate) / 8ULL / 90000ULL;
752         
753         seekToPosition(decoding_demux, offset);
754         return 0;
755 }
756
757 RESULT eDVBChannel::seekToPosition(iDVBDemux *decoding_demux, const off_t &r)
758 {
759                         /* when seeking, we have to ensure that all buffers are flushed.
760                            there are basically 3 buffers:
761                            a.) the filepush's internal buffer
762                            b.) the PVR buffer (before demux)
763                            c.) the ratebuffer (after demux)
764                            
765                            it's important to clear them in the correct order, otherwise
766                            the ratebuffer (for example) would immediately refill from
767                            the not-yet-flushed PVR buffer.
768                         */
769         eDebug("eDVBChannel: seekToPosition .. %llx", r);
770         m_pvr_thread->pause();
771
772                 /* flush internal filepush buffer */
773         m_pvr_thread->flush();
774
775                 /* HACK: flush PVR buffer */
776         ::ioctl(m_pvr_fd_dst, 0);
777         
778                 /* flush ratebuffers (video, audio) */
779         if (decoding_demux)
780                 decoding_demux->flush();
781
782                 /* demux will also flush all decoder.. */
783         m_pvr_thread->seek(SEEK_SET, r);
784         m_pvr_thread->resume();
785         return 0;
786 }