From 359e90b8a7fee368e496b79ab253045b989fa6a5 Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sat, 22 Jun 2002 13:45:53 +0200 Subject: [PATCH] Activated transfer mode --- HISTORY | 1 + Makefile | 4 +- device.c | 16 ++++--- device.h | 8 ++-- dvbplayer.c | 4 +- eitscan.c | 4 +- menu.c | 4 +- transfer.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++ transfer.h | 35 +++++++++++++++ 9 files changed, 181 insertions(+), 17 deletions(-) create mode 100644 transfer.c create mode 100644 transfer.h diff --git a/HISTORY b/HISTORY index 00a64394..3b881cb2 100644 --- a/HISTORY +++ b/HISTORY @@ -1352,3 +1352,4 @@ Video Disk Recorder Revision History - Added Hungarian language texts (thanks to Istvan Koenigsberger and Guido Josten). - Activated cutting. +- Activated transfer mode. diff --git a/Makefile b/Makefile index f3b37504..7e922184 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ # See the main source file 'vdr.c' for copyright information and # how to reach the author. # -# $Id: Makefile 1.41 2002/06/22 09:49:29 kls Exp $ +# $Id: Makefile 1.42 2002/06/22 10:21:56 kls Exp $ .DELETE_ON_ERROR: @@ -24,7 +24,7 @@ DTVLIB = $(DTVDIR)/libdtv.a OBJS = audio.o config.o cutter.o device.o dvbplayer.o dvbosd.o eit.o eitscan.o font.o i18n.o\ interface.o menu.o menuitems.o osdbase.o osd.o player.o plugin.o receiver.o\ recorder.o recording.o remote.o remux.o ringbuffer.o status.o svdrp.o thread.o\ - tools.o vdr.o videodir.o + tools.o transfer.o vdr.o videodir.o OSDFONT = -adobe-helvetica-medium-r-normal--23-*-100-100-p-*-iso8859-1 FIXFONT = -adobe-courier-bold-r-normal--25-*-100-100-m-*-iso8859-1 diff --git a/device.c b/device.c index fe756592..7bce6c4e 100644 --- a/device.c +++ b/device.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: device.c 1.2 2002/06/16 13:23:31 kls Exp $ + * $Id: device.c 1.3 2002/06/22 13:45:53 kls Exp $ */ #include "device.h" @@ -21,6 +21,7 @@ extern "C" { #include "player.h" #include "receiver.h" #include "status.h" +#include "transfer.h" #define DEV_VIDEO "/dev/video" #define DEV_OST_OSD "/dev/ost/osd" @@ -105,6 +106,7 @@ cDevice::cDevice(int n) currentChannel = 0; frequency = 0; + transfer = NULL; mute = false; volume = Setup.CurrentVolume; @@ -118,6 +120,7 @@ cDevice::cDevice(int n) cDevice::~cDevice() { + delete transfer; delete dvrFileName; delete siProcessor; Detach(player); @@ -456,7 +459,7 @@ bool cDevice::SetPid(int fd, dmxPesType_t PesType, int Pid, dmxOutput_t Output) eSetChannelResult cDevice::SetChannel(int ChannelNumber, int Frequency, char Polarization, int Diseqc, int Srate, int Vpid, int Apid, int Tpid, int Ca, int Pnr) { - //XXX+StopTransfer(); + DELETENULL(transfer); //XXX+StopReplay(); cStatus::MsgChannelSwitch(this, 0); @@ -621,8 +624,9 @@ eSetChannelResult cDevice::SetChannel(int ChannelNumber, int Frequency, char Pol cDevice *CaDevice = GetDevice(Ca, 0); if (CaDevice && !CaDevice->Receiving()) { if ((Result = CaDevice->SetChannel(ChannelNumber, Frequency, Polarization, Diseqc, Srate, Vpid, Apid, Tpid, Ca, Pnr)) == scrOk) { - //XXX+SetModeReplay(); - //XXX+transferringFromDevice = CaDevice->StartTransfer(fd_video); + transfer = new cTransfer(Vpid, Apid, 0, 0, 0);//XXX+ + AttachPlayer(transfer); + CaDevice->AttachReceiver(transfer); } } else @@ -739,7 +743,7 @@ bool cDevice::Replaying(void) return player != NULL; } -bool cDevice::Attach(cPlayer *Player) +bool cDevice::AttachPlayer(cPlayer *Player) { if (Receiving()) { esyslog("ERROR: attempt to attach a cPlayer while receiving on device %d - ignored", CardIndex() + 1); @@ -958,7 +962,7 @@ void cDevice::Action(void) dsyslog("receiver thread ended on device %d (pid=%d)", CardIndex() + 1, getpid()); } -bool cDevice::Attach(cReceiver *Receiver) +bool cDevice::AttachReceiver(cReceiver *Receiver) { //XXX+ check for same transponder??? if (!Receiver) diff --git a/device.h b/device.h index e598430a..8c68ee0a 100644 --- a/device.h +++ b/device.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: device.h 1.1 2002/06/10 16:30:00 kls Exp $ + * $Id: device.h 1.2 2002/06/22 13:34:55 kls Exp $ */ #ifndef __DEVICE_H @@ -33,6 +33,7 @@ enum eSetChannelResult { scrOk, scrNoTransfer, scrFailed }; class cPlayer; class cReceiver; +class cTransfer; class cDevice : cThread { friend class cOsd;//XXX @@ -106,6 +107,7 @@ public: private: int currentChannel; int frequency; + cTransfer *transfer; public: eSetChannelResult SetChannel(int ChannelNumber, int Frequency, char Polarization, int Diseqc, int Srate, int Vpid, int Apid, int Tpid, int Ca, int Pnr); static int CurrentChannel(void) { return primaryDevice ? primaryDevice->currentChannel : 0; } @@ -172,7 +174,7 @@ public: // Returns true if we are currently replaying. void StopReplay(void); // Stops the current replay session (if any). - bool Attach(cPlayer *Player); + bool AttachPlayer(cPlayer *Player); void Detach(cPlayer *Player); virtual int PlayVideo(const uchar *Data, int Length); virtual int PlayAudio(const uchar *Data, int Length); @@ -192,7 +194,7 @@ public: // Returns the ca of the current receiving session. bool Receiving(void); // Returns true if we are currently receiving. - bool Attach(cReceiver *Receiver); + bool AttachReceiver(cReceiver *Receiver); void Detach(cReceiver *Receiver); }; diff --git a/dvbplayer.c b/dvbplayer.c index f18eb84e..3027e37d 100644 --- a/dvbplayer.c +++ b/dvbplayer.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: dvbplayer.c 1.2 2002/06/22 10:11:59 kls Exp $ + * $Id: dvbplayer.c 1.3 2002/06/22 13:35:36 kls Exp $ */ #include "dvbplayer.h" @@ -644,7 +644,7 @@ bool cDvbPlayerControl::Start(const char *FileName) { delete player; player = new cDvbPlayer(FileName); - if (cDevice::PrimaryDevice()->Attach(player)) + if (cDevice::PrimaryDevice()->AttachPlayer(player)) return true; Stop(); return false; diff --git a/eitscan.c b/eitscan.c index 21fbe74e..a275abe0 100644 --- a/eitscan.c +++ b/eitscan.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: eitscan.c 1.2 2002/06/10 16:30:00 kls Exp $ + * $Id: eitscan.c 1.3 2002/06/22 13:02:40 kls Exp $ */ #include "eitscan.h" @@ -52,7 +52,7 @@ void cEITScanner::Process(void) cDevice *Device = cDevice::GetDevice(i + 1, MAXPRIORITY + 1); if (Device) { if (Device != cDevice::PrimaryDevice() || (cDevice::NumDevices() == 1 && Setup.EPGScanTimeout && now - lastActivity > Setup.EPGScanTimeout * 3600)) { - if (!(Device->Receiving() || Device->Replaying()/*XXX+ || Device->Transferring()XXX*/)) { + if (!(Device->Receiving() || Device->Replaying())) { int oldCh = lastChannel; int ch = oldCh + 1; while (ch != oldCh) { diff --git a/menu.c b/menu.c index 29703da1..904a630a 100644 --- a/menu.c +++ b/menu.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: menu.c 1.198 2002/06/22 09:55:58 kls Exp $ + * $Id: menu.c 1.199 2002/06/22 13:36:10 kls Exp $ */ #include "menu.h" @@ -2442,7 +2442,7 @@ cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer) cRecordingUserCommand::InvokeCommand(RUC_BEFORERECORDING, fileName); cChannel *ch = Channels.GetByNumber(timer->channel); recorder = new cRecorder(fileName, ch->ca, timer->priority, ch->vpid, ch->apid1, ch->apid2, ch->dpid1, ch->dpid2); - if (device->Attach(recorder)) { + if (device->AttachReceiver(recorder)) { Recording.WriteSummary(); cStatus::MsgRecording(device, fileName); Interface->DisplayRecording(device->CardIndex(), true); diff --git a/transfer.c b/transfer.c new file mode 100644 index 00000000..0e0a7083 --- /dev/null +++ b/transfer.c @@ -0,0 +1,122 @@ +/* + * transfer.c: Transfer mode + * + * See the main source file 'vdr.c' for copyright information and + * how to reach the author. + * + * $Id: transfer.c 1.1 2002/06/22 13:39:23 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) +{ + 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*/ +} diff --git a/transfer.h b/transfer.h new file mode 100644 index 00000000..060401f7 --- /dev/null +++ b/transfer.h @@ -0,0 +1,35 @@ +/* + * transfer.h: Transfer mode + * + * See the main source file 'vdr.c' for copyright information and + * how to reach the author. + * + * $Id: transfer.h 1.1 2002/06/22 13:38:23 kls Exp $ + */ + +#ifndef __TRANSFER_H +#define __TRANSFER_H + +#include "player.h" +#include "receiver.h" +#include "remux.h" +#include "ringbuffer.h" +#include "thread.h" + +class cTransfer : public cReceiver, public cPlayer, public cThread { +private: + cRingBufferLinear *ringBuffer; + cRemux *remux; + bool gotBufferReserve; + bool active; +protected: + virtual void Activate(bool On); + virtual void Receive(uchar *Data, int Length); + virtual void Action(void); +public: + cTransfer(int VPid, int APid1, int APid2, int DPid1, int DPid2); + virtual ~cTransfer(); + void SetAudioPid(int APid); + }; + +#endif //__TRANSFER_H