vdr/transfer.c
Klaus Schmidinger d08073815d Version 1.1.11
- Fixed an incomplete initialization of the filter parameters in eit.c (thanks
  to Jeremy Hall).
- Fixed the 'newplugin' script for use with the NEWSTRUCT driver (thanks to
  Andreas Schultz for reporting this one). If you have already created a plugin
  directory and Makefile with 'newplugin', please apply the following patch to it:

  -------------------------------------------------------
  --- Makefile    2002/06/10 16:24:06     1.4
  +++ Makefile    2002/09/17 15:36:36     1.5
  @@ -15,7 +15,12 @@

   ### The directory environment:

  +ifdef NEWSTRUCT
  +DVBDIR = ../../../../DVB/include
  +DEFINES += -DNEWSTRUCT
  +else
   DVBDIR = ../../../../DVB/ost/include
  +endif
   VDRDIR = ../../..
   VDRINC = $(VDRDIR)/include
   LIBDIR = ../../lib
  @@ -34,7 +39,7 @@

   INCLUDES = -I$(VDRINC) -I$(DVBDIR)

  -DEFINES = -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
  +DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"'

   ### The object files (add further files here):
  -------------------------------------------------------

  This is the diff for the 'setup' example that comes with VDR, so your line
  numbers may be different.
- Added a missing 'public' keyword in device.h (thanks to Martin Hammerschmid).
- Fixed a race condition when starting 'Transfer Mode'.
- Rearranged the remote control key handling to allow plugins to implement
  additional types of remote controls (see PLUGINS.html, section "Remote Control").
  The previously used files 'keys.conf' and 'keys-pc.conf' have been replaced
  by the file 'remote.conf', which holds the key definitions of all remote controls.
- The LIRC remote control keys are now handled just like the keyboard and RCU keys.
  This means that you can use the lircd.conf file as is for your remote control,
  without the need of editing it to make the key names the same as used in VDR.
  When first starting VDR it will go into the "Learning keys" mode and ask you
  to press the various keys. The resulting key assignment will be stored in
  the file 'remote.conf'.
  Since I have no way of testing the LIRC support, I hope I didn't break it in
  the process...
- While learning the remote control keys it is now possible to press the 'Menu'
  key to skip the definition of keys that are not available on your particular
  RC unit.
- Fixed handling DVD subtitles in the SPU decoder (thanks to Andreas Schultz).
- Avoiding restarts due to 'panic level' when switching channels on the primary
  device during EPG scan.
2002-09-29 18:00:00 +02:00

138 lines
3.4 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.3 2002/09/22 09:50:48 kls Exp $
*/
#include "transfer.h"
//XXX+ also used in recorder.c - find a better place???
// The size of the array used to buffer video data:
// (must be larger than MINVIDEODATA - see remux.h)
#define VIDEOBUFSIZE MEGABYTE(1)
// --- cTransfer -------------------------------------------------------------
cTransfer::cTransfer(int VPid, int APid1, int APid2, int DPid1, int DPid2)
:cReceiver(0, 0, 5, VPid, APid1, APid2, DPid1, DPid2)
{
ringBuffer = new cRingBufferLinear(VIDEOBUFSIZE, true);
remux = new cRemux(VPid, APid1, APid2, DPid1, DPid2);
gotBufferReserve = false;
active = false;
}
cTransfer::~cTransfer()
{
cReceiver::Detach();
cPlayer::Detach();
delete remux;
delete ringBuffer;
}
void cTransfer::Activate(bool On)
{
if (On) {
if (!active)
Start();
}
else if (active) {
active = false;
Cancel(3);
}
}
void cTransfer::Receive(uchar *Data, int Length)
{
if (IsAttached()) {
int p = ringBuffer->Put(Data, Length);
if (p != Length && active)
esyslog("ERROR: ring buffer overflow (%d bytes dropped)", Length - p);
}
}
void cTransfer::Action(void)
{
dsyslog("transfer thread started (pid=%d)", getpid());
uchar b[MINVIDEODATA];
int r = 0;
active = true;
while (active) {
//XXX+ Maybe we need this to avoid "buffer empty" log messages from the driver.
//XXX+ But then again, it appears to play just fine without this...
/*
if (!gotBufferReserve) {
if (ringBuffer->Available() < 4 * MAXFRAMESIZE) {
usleep(100000); // allow the buffer to collect some reserve
continue;
}
else
gotBufferReserve = true;
}
*/
// Get data from the buffer:
int g = ringBuffer->Get(b + r, sizeof(b) - r);
if (g > 0)
r += g;
// Play the data:
if (r > 0) {
int Count = r, Result;
const uchar *p = remux->Process(b, Count, Result);
if (p) {
//XXX+ StripAudio???
while (Result > 0 && active) {
int w = PlayVideo(p, Result);
if (w > 0) {
p += w;
Result -= w;
}
else if (w < 0 && FATALERRNO) {
LOG_ERROR;
break;
}
}
}
if (Count > 0) {
r -= Count;
if (r > 0)
memmove(b, b + Count, r);
}
}
}
dsyslog("transfer thread ended (pid=%d)", getpid());
}
void cTransfer::SetAudioPid(int APid)
{
/*XXX+
Clear();
//XXX we may need to have access to the audio device, too, in order to clear it
CHECK(ioctl(toDevice, VIDEO_CLEAR_BUFFER));
gotBufferReserve = false;
remux.SetAudioPid(APid);
XXX*/
}
// --- cTransferControl ------------------------------------------------------
cTransferControl::cTransferControl(cDevice *ReceiverDevice, int VPid, int APid1, int APid2, int DPid1, int DPid2)
:cControl(transfer = new cTransfer(VPid, APid1, APid2, DPid1, DPid2), true)
{
ReceiverDevice->AttachReceiver(transfer);
}
cTransferControl::~cTransferControl()
{
delete transfer;
}