mirror of
https://github.com/vdr-projects/vdr.git
synced 2025-03-01 10:50:46 +00:00
- Fixed a second place where a message should be given when an instant recording is started (reported by Jesus Bravo Alvarez). - Modified logging so that even on NPTL systems each line in the log file shows the individual thread's pid (based on a suggestion from Francois-Xavier Kowalski). - Fixed a problem with @plugin in keymacros.conf in case the named plugin is not loaded (reported by Franz Gangkofer). - Fixed a crash after executing the SVDRP command CLRE, caused by dangling 'schedule' pointers from cChannel objects (reported by Malte Schröder). - Updated the Finnish OSD texts (thanks to Rolf Ahrenberg). - Improved NULL checking in strreplace(). - Fixed a crash in the Schedule menu with events that have no title (reported by Rolf Ahrenberg). cEvent::FixEpgBugs() now assigns a "No title" string to events that have no title. - Updated the Estonian OSD texts (thanks to Arthur Konovalov). - Recordings are now only started if there is at least 300MB free disk space (suggested by Markus Hahn). - When entering text via the numeric keys, the cursor now automatically advances (based on a patch from Rolf Ahrenberg). - Updated the Polish OSD texts and the fontosd-iso8859-2.c file (thanks to Jaroslaw Swierczynski). - Disabled the "buffer reserve" in Transfer Mode. Last chance to complain if you really need it - it will be completely removed in the next version. If you are experiencing problems with a/v running out of sync, try the latest driver and firmware (if you are using a full featured DVB card). - Switching channels with the Up/Down or Channel+/Channel- keys now works a lot faster when the repeat function kicks in, by not actually switching the channel every time, but rather only displaying the channel info and doing the final switch when the key is released. - The channel display is now updated _before_ the channel is switched. - Added a missing initialization of 'timeout' in the cDisplayChannel constructor. - Fixed detecting if there can be any useful further input when entering channel numbers (thanks to Thomas Bergwinkl). - Updated the Spanish OSD texts (thanks to Jesus Bravo Alvarez). - Fixed handling the '0' key for switching between the last two channels (thanks to Thomas Bergwinkl).
161 lines
5.1 KiB
C
161 lines
5.1 KiB
C
/*
|
|
* transfer.c: Transfer mode
|
|
*
|
|
* See the main source file 'vdr.c' for copyright information and
|
|
* how to reach the author.
|
|
*
|
|
* $Id: transfer.c 1.31 2006/01/21 14:13:16 kls Exp $
|
|
*/
|
|
|
|
#include "transfer.h"
|
|
|
|
#define TRANSFERBUFSIZE MEGABYTE(2)
|
|
#define POLLTIMEOUTS_BEFORE_DEVICECLEAR 6
|
|
|
|
// --- cTransfer -------------------------------------------------------------
|
|
|
|
cTransfer::cTransfer(int VPid, const int *APids, const int *DPids, const int *SPids)
|
|
:cReceiver(0, -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);
|
|
needsBufferReserve = Setup.UseDolbyDigital && VPid != 0 && DPids && DPids[0] != 0;
|
|
}
|
|
|
|
cTransfer::~cTransfer()
|
|
{
|
|
cReceiver::Detach();
|
|
cPlayer::Detach();
|
|
delete remux;
|
|
delete ringBuffer;
|
|
}
|
|
|
|
void cTransfer::Activate(bool On)
|
|
{
|
|
if (On)
|
|
Start();
|
|
else
|
|
Cancel(3);
|
|
}
|
|
|
|
void cTransfer::Receive(uchar *Data, int Length)
|
|
{
|
|
if (IsAttached() && Running()) {
|
|
int p = ringBuffer->Put(Data, Length);
|
|
if (p != Length && Running())
|
|
ringBuffer->ReportOverflow(Length - p);
|
|
return;
|
|
}
|
|
}
|
|
|
|
#define FW_NEEDS_BUFFER_RESERVE_FOR_AC3
|
|
#ifdef FW_NEEDS_BUFFER_RESERVE_FOR_AC3
|
|
//XXX This is a very ugly hack to allow cDvbOsd to reduce the buffer
|
|
//XXX requirements in cTransfer if it detects a 4MB full featured DVB card.
|
|
bool DvbCardWith4MBofSDRAM = false;
|
|
#endif
|
|
|
|
void cTransfer::Action(void)
|
|
{
|
|
int PollTimeouts = 0;
|
|
uchar *p = NULL;
|
|
int Result = 0;
|
|
#ifdef FW_NEEDS_BUFFER_RESERVE_FOR_AC3
|
|
bool GotBufferReserve = false;
|
|
GotBufferReserve = true; //XXX remove this line if you absolutely need the buffer reserve
|
|
int RequiredBufferReserve = KILOBYTE(DvbCardWith4MBofSDRAM ? 288 : 576);
|
|
#endif
|
|
while (Running()) {
|
|
#ifdef FW_NEEDS_BUFFER_RESERVE_FOR_AC3
|
|
if (needsBufferReserve && !GotBufferReserve) {
|
|
//XXX For dolby we've to fill the buffer because the firmware does
|
|
//XXX not decode dolby but use a PCM stream for transport, therefore
|
|
//XXX the firmware has not enough buffer for noiseless skipping early
|
|
//XXX PCM samples (each dolby frame requires 6144 bytes in PCM and
|
|
//XXX audio is mostly to early in comparison to video).
|
|
//XXX To resolve this, the remuxer or PlayPes() should synchronize
|
|
//XXX audio with the video frames. 2004/09/09 Werner
|
|
if (ringBuffer->Available() < RequiredBufferReserve) { // used to be MAXFRAMESIZE, but the HDTV value of KILOBYTE(512) is way too much here
|
|
cCondWait::SleepMs(20); // allow the buffer to collect some reserve
|
|
continue;
|
|
}
|
|
else
|
|
GotBufferReserve = true;
|
|
}
|
|
#endif
|
|
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;
|
|
#ifdef FW_NEEDS_BUFFER_RESERVE_FOR_AC3
|
|
GotBufferReserve = false;
|
|
#endif
|
|
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;
|
|
#ifdef FW_NEEDS_BUFFER_RESERVE_FOR_AC3
|
|
GotBufferReserve = false;
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// --- cTransferControl ------------------------------------------------------
|
|
|
|
cDevice *cTransferControl::receiverDevice = NULL;
|
|
|
|
cTransferControl::cTransferControl(cDevice *ReceiverDevice, int VPid, const int *APids, const int *DPids, const int *SPids)
|
|
:cControl(transfer = new cTransfer(VPid, APids, DPids, SPids), true)
|
|
{
|
|
ReceiverDevice->AttachReceiver(transfer);
|
|
receiverDevice = ReceiverDevice;
|
|
}
|
|
|
|
cTransferControl::~cTransferControl()
|
|
{
|
|
receiverDevice = NULL;
|
|
delete transfer;
|
|
}
|