mirror of
https://github.com/vdr-projects/vdr.git
synced 2025-03-01 10:50:46 +00:00
First step towards switching to TS (Transport Stream) as recording format
This commit is contained in:
95
transfer.c
95
transfer.c
@@ -4,109 +4,52 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: transfer.c 1.34 2007/01/07 14:45:28 kls Exp $
|
||||
* $Id: transfer.c 2.1 2008/08/15 14:32:12 kls Exp $
|
||||
*/
|
||||
|
||||
#include "transfer.h"
|
||||
|
||||
#define TRANSFERBUFSIZE MEGABYTE(2)
|
||||
#define POLLTIMEOUTS_BEFORE_DEVICECLEAR 6
|
||||
|
||||
// --- cTransfer -------------------------------------------------------------
|
||||
|
||||
cTransfer::cTransfer(tChannelID ChannelID, int VPid, const int *APids, const int *DPids, const int *SPids)
|
||||
:cReceiver(ChannelID, -1, VPid, APids, Setup.UseDolbyDigital ? DPids : NULL, SPids)
|
||||
,cThread("transfer")
|
||||
{
|
||||
ringBuffer = new cRingBufferLinear(TRANSFERBUFSIZE, TS_SIZE * 2, true, "Transfer");
|
||||
remux = new cRemux(VPid, APids, Setup.UseDolbyDigital ? DPids : NULL, SPids);
|
||||
patPmtGenerator.GeneratePmt(ChannelID);
|
||||
}
|
||||
|
||||
cTransfer::~cTransfer()
|
||||
{
|
||||
cReceiver::Detach();
|
||||
cPlayer::Detach();
|
||||
delete remux;
|
||||
delete ringBuffer;
|
||||
}
|
||||
|
||||
void cTransfer::Activate(bool On)
|
||||
{
|
||||
if (On)
|
||||
Start();
|
||||
else {
|
||||
Cancel(3);
|
||||
cPlayer::Detach();
|
||||
if (On) {
|
||||
PlayTs(patPmtGenerator.GetPat(), TS_SIZE);
|
||||
int Index = 0;
|
||||
while (uchar *pmt = patPmtGenerator.GetPmt(Index))
|
||||
PlayTs(pmt, TS_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
void cTransfer::Receive(uchar *Data, int Length)
|
||||
{
|
||||
if (cPlayer::IsAttached() && Running()) {
|
||||
int p = ringBuffer->Put(Data, Length);
|
||||
if (p != Length && Running())
|
||||
ringBuffer->ReportOverflow(Length - p);
|
||||
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:
|
||||
for (int i = 0; i < 100; i++) {
|
||||
if (PlayTs(Data, Length) > 0)
|
||||
return;
|
||||
fprintf(stderr, "-");//XXX just for testing - remove when stable
|
||||
cCondWait::SleepMs(10);
|
||||
}
|
||||
esyslog("ERROR: TS packet not accepted in Transfer Mode");
|
||||
}
|
||||
}
|
||||
|
||||
void cTransfer::Action(void)
|
||||
{
|
||||
int PollTimeouts = 0;
|
||||
uchar *p = NULL;
|
||||
int Result = 0;
|
||||
while (Running()) {
|
||||
int Count;
|
||||
uchar *b = ringBuffer->Get(Count);
|
||||
if (b) {
|
||||
if (ringBuffer->Available() > TRANSFERBUFSIZE * 9 / 10) {
|
||||
// If the buffer runs full, we have no chance of ever catching up
|
||||
// since the data comes in at the same rate as it goes out (it's "live").
|
||||
// So let's clear the buffer instead of suffering from permanent
|
||||
// overflows.
|
||||
dsyslog("clearing transfer buffer to avoid overflows");
|
||||
DeviceClear();
|
||||
ringBuffer->Clear();
|
||||
remux->Clear();
|
||||
PlayPes(NULL, 0);
|
||||
p = NULL;
|
||||
continue;
|
||||
}
|
||||
Count = remux->Put(b, Count);
|
||||
if (Count)
|
||||
ringBuffer->Del(Count);
|
||||
}
|
||||
if (!p)
|
||||
p = remux->Get(Result);
|
||||
if (p) {
|
||||
cPoller Poller;
|
||||
if (DevicePoll(Poller, 100)) {
|
||||
PollTimeouts = 0;
|
||||
int w = PlayPes(p, Result);
|
||||
if (w > 0) {
|
||||
p += w;
|
||||
Result -= w;
|
||||
remux->Del(w);
|
||||
if (Result <= 0)
|
||||
p = NULL;
|
||||
}
|
||||
else if (w < 0 && FATALERRNO)
|
||||
LOG_ERROR;
|
||||
}
|
||||
else {
|
||||
PollTimeouts++;
|
||||
if (PollTimeouts == POLLTIMEOUTS_BEFORE_DEVICECLEAR) {
|
||||
dsyslog("clearing device because of consecutive poll timeouts");
|
||||
DeviceClear();
|
||||
ringBuffer->Clear();
|
||||
remux->Clear();
|
||||
PlayPes(NULL, 0);
|
||||
p = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- cTransferControl ------------------------------------------------------
|
||||
|
||||
cDevice *cTransferControl::receiverDevice = NULL;
|
||||
|
||||
Reference in New Issue
Block a user