2002-06-22 13:45:53 +02:00
|
|
|
/*
|
|
|
|
* transfer.c: Transfer mode
|
|
|
|
*
|
|
|
|
* See the main source file 'vdr.c' for copyright information and
|
|
|
|
* how to reach the author.
|
|
|
|
*
|
2022-12-05 14:45:51 +01:00
|
|
|
* $Id: transfer.c 5.1 2022/12/05 14:45:51 kls Exp $
|
2002-06-22 13:45:53 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "transfer.h"
|
|
|
|
|
|
|
|
// --- cTransfer -------------------------------------------------------------
|
|
|
|
|
2010-01-30 11:10:25 +01:00
|
|
|
cTransfer::cTransfer(const cChannel *Channel)
|
2012-03-02 10:19:00 +01:00
|
|
|
:cReceiver(Channel, TRANSFERPRIORITY)
|
2002-06-22 13:45:53 +02:00
|
|
|
{
|
2017-12-07 15:05:48 +01:00
|
|
|
lastErrorReport = 0;
|
|
|
|
numLostPackets = 0;
|
2010-01-30 11:10:25 +01:00
|
|
|
patPmtGenerator.SetChannel(Channel);
|
2002-06-22 13:45:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
cTransfer::~cTransfer()
|
|
|
|
{
|
|
|
|
cReceiver::Detach();
|
|
|
|
cPlayer::Detach();
|
|
|
|
}
|
|
|
|
|
|
|
|
void cTransfer::Activate(bool On)
|
|
|
|
{
|
2008-08-15 14:49:34 +02:00
|
|
|
if (On) {
|
|
|
|
PlayTs(patPmtGenerator.GetPat(), TS_SIZE);
|
|
|
|
int Index = 0;
|
|
|
|
while (uchar *pmt = patPmtGenerator.GetPmt(Index))
|
|
|
|
PlayTs(pmt, TS_SIZE);
|
2007-01-07 14:46:14 +01:00
|
|
|
}
|
2009-01-16 15:16:08 +01:00
|
|
|
else
|
|
|
|
cPlayer::Detach();
|
2002-06-22 13:45:53 +02:00
|
|
|
}
|
|
|
|
|
2013-08-22 12:35:10 +02:00
|
|
|
#define MAXRETRIES 20 // max. number of retries for a single TS packet
|
2013-01-20 13:40:30 +01:00
|
|
|
#define RETRYWAIT 5 // time (in ms) between two retries
|
2017-12-07 15:05:48 +01:00
|
|
|
#define ERRORDELTA 60 // seconds before reporting lost TS packets again
|
2013-01-20 13:40:30 +01:00
|
|
|
|
2015-09-05 11:49:56 +02:00
|
|
|
void cTransfer::Receive(const uchar *Data, int Length)
|
2002-06-22 13:45:53 +02:00
|
|
|
{
|
2008-08-15 14:49:34 +02:00
|
|
|
if (cPlayer::IsAttached()) {
|
|
|
|
// Transfer Mode means "live tv", so there's no point in doing any additional
|
|
|
|
// buffering here. The TS packets *must* get through here! However, every
|
|
|
|
// now and then there may be conditions where the packet just can't be
|
|
|
|
// handled when offered the first time, so that's why we try several times:
|
2013-01-20 13:40:30 +01:00
|
|
|
for (int i = 0; i < MAXRETRIES; i++) {
|
2013-03-01 10:02:01 +01:00
|
|
|
if (PlayTs(Data, Length) > 0)
|
2008-08-15 14:49:34 +02:00
|
|
|
return;
|
2013-01-20 13:40:30 +01:00
|
|
|
cCondWait::SleepMs(RETRYWAIT);
|
2008-08-15 14:49:34 +02:00
|
|
|
}
|
2013-03-01 10:02:01 +01:00
|
|
|
DeviceClear();
|
2017-12-07 15:05:48 +01:00
|
|
|
numLostPackets++;
|
|
|
|
if (time(NULL) - lastErrorReport > ERRORDELTA) {
|
|
|
|
esyslog("ERROR: %d TS packet(s) not accepted in Transfer Mode", numLostPackets);
|
|
|
|
numLostPackets = 0;
|
|
|
|
lastErrorReport = time(NULL);
|
|
|
|
}
|
2002-09-22 09:52:38 +02:00
|
|
|
}
|
2002-06-22 13:45:53 +02:00
|
|
|
}
|
|
|
|
|
2002-06-23 12:59:58 +02:00
|
|
|
// --- cTransferControl ------------------------------------------------------
|
|
|
|
|
2003-05-11 09:01:51 +02:00
|
|
|
cDevice *cTransferControl::receiverDevice = NULL;
|
|
|
|
|
2010-01-30 11:10:25 +01:00
|
|
|
cTransferControl::cTransferControl(cDevice *ReceiverDevice, const cChannel *Channel)
|
2022-12-05 14:45:51 +01:00
|
|
|
:cControl(NULL, true)
|
2002-06-23 12:59:58 +02:00
|
|
|
{
|
2022-12-05 14:45:51 +01:00
|
|
|
transfer = new cTransfer(Channel);
|
|
|
|
SetPlayer(transfer);
|
2002-06-23 12:59:58 +02:00
|
|
|
ReceiverDevice->AttachReceiver(transfer);
|
2003-05-11 09:01:51 +02:00
|
|
|
receiverDevice = ReceiverDevice;
|
2002-06-23 12:59:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
cTransferControl::~cTransferControl()
|
|
|
|
{
|
2003-05-11 09:01:51 +02:00
|
|
|
receiverDevice = NULL;
|
2002-06-23 12:59:58 +02:00
|
|
|
delete transfer;
|
|
|
|
}
|