|
+ |
Important modifications introduced in version 1.3.18 are marked like this.
|
+ |
+Important modifications introduced in version 1.3.19 are marked like this.
+ |
VDR provides an easy to use plugin interface that allows additional functionality
to be added to the program by implementing a dynamically loadable library file.
@@ -73,11 +73,9 @@ structures and allows it to hook itself into specific areas to perform special a
Status monitor
Players
Receivers
-
The On Screen Display
- |
+
@@ -1023,7 +1021,7 @@ public:
Take a look at the files player.h and dvbplayer.c to see how VDR implements
its own player for the VDR recordings.
- |
+ |
To play the actual data, the player needs to call its member function
@@ -1046,7 +1044,7 @@ bool DevicePoll(cPoller &Poller, int TimeoutMs = 0);
to determine whether the device is ready for further data.
- |
+ |
By default all audio track handling is done by the device a player is
attached to.
If the player can provide more than a single audio track, and has special
@@ -1183,7 +1181,9 @@ public:
};
cMyReceiver::cMyReceiver(int Pid)
-:cReceiver(0, -1, 1, Pid)
+ |
+:cReceiver(0, -1, Pid)
+ |
{
}
@@ -1223,7 +1223,6 @@ Mode).
If the cReceiver isn't needed any more, it may simply be deleted
and will automatically detach itself from the cDevice.
-
- |
+ |
The On Screen Display
Window to the world
@@ -1362,7 +1360,7 @@ public:
virtual cSkinDisplayMenu *DisplayMenu(void);
virtual cSkinDisplayReplay *DisplayReplay(bool ModeOnly);
virtual cSkinDisplayVolume *DisplayVolume(void);
- |
+ |
virtual cSkinDisplayMessage *DisplayTrack(int NumTracks, const char * const *Tracks);
|
virtual cSkinDisplayMessage *DisplayMessage(void);
@@ -1384,7 +1382,7 @@ new cMySkin;
in the Start() function of your plugin.
Do not delete this object, it will be automatically deleted when the program ends.
- |
+ |
In order to be able to easily identify plugins that implement a skin it is recommended
that the name of such a plugin should be
@@ -1495,7 +1493,7 @@ repectively.
If the device can provide more than a single audio track, it can implement the
following function to make them available:
- |
+ |
virtual void SetAudioTrackDevice(eTrackType Type);
virtual int GetAudioChannelDevice(void);
@@ -1558,7 +1556,6 @@ virtual void SetVideoFormat(bool VideoFormat16_9);
virtual void SetVolumeDevice(int Volume);
|
- |
Section Filtering
@@ -1583,12 +1580,11 @@ from its constructor.
See Filters on how to set up actual filters that can
handle section data.
- |
On Screen Display
- |
+ |
If your device provides On Screen Display (OSD) capabilities (which every device
that is supposed to be used as a primary device should do), it shall implement
an "OSD provider" class, derived from cOsdProvider, which, when its CreateOsd()
diff --git a/channels.c b/channels.c
index 9403ef52..5c0456b6 100644
--- a/channels.c
+++ b/channels.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: channels.c 1.33 2004/12/26 12:34:52 kls Exp $
+ * $Id: channels.c 1.34 2005/01/16 13:49:30 kls Exp $
*/
#include "channels.h"
@@ -193,6 +193,7 @@ cChannel::cChannel(const cChannel &Channel)
ppid = 0;
apids[0] = 0;
dpids[0] = 0;
+ spids[0] = 0;
tpid = 0;
caids[0] = 0;
nid = 0;
@@ -421,8 +422,8 @@ void cChannel::SetPids(int Vpid, int Ppid, int *Apids, char ALangs[][4], int *Dp
if (!modified)
modified = IntArraysDiffer(apids, Apids, alangs, ALangs) || IntArraysDiffer(dpids, Dpids, dlangs, DLangs);
if (modified) {
- char OldApidsBuf[MAXAPIDS * 2 * 10 + 10]; // 2: Apids and Dpids, 10: 5 digits plus delimiting ',' or ';' plus optional '=cod', +10: paranoia
- char NewApidsBuf[MAXAPIDS * 2 * 10 + 10];
+ char OldApidsBuf[(MAXAPIDS + MAXDPIDS) * 10 + 10]; // 10: 5 digits plus delimiting ',' or ';' plus optional '=cod', +10: paranoia
+ char NewApidsBuf[(MAXAPIDS + MAXDPIDS) * 10 + 10];
char *q = OldApidsBuf;
q += IntArrayToString(q, apids, 10, alangs);
if (dpids[0]) {
@@ -443,6 +444,8 @@ void cChannel::SetPids(int Vpid, int Ppid, int *Apids, char ALangs[][4], int *Dp
for (int i = 0; i <= MAXAPIDS; i++) { // <= to copy the terminating 0
apids[i] = Apids[i];
strn0cpy(alangs[i], ALangs[i], 4);
+ }
+ for (int i = 0; i <= MAXDPIDS; i++) { // <= to copy the terminating 0
dpids[i] = Dpids[i];
strn0cpy(dlangs[i], DLangs[i], 4);
}
@@ -623,7 +626,7 @@ cString cChannel::ToText(const cChannel *Channel)
if (Channel->ppid && Channel->ppid != Channel->vpid)
q += snprintf(q, sizeof(vpidbuf) - (q - vpidbuf), "+%d", Channel->ppid);
*q = 0;
- char apidbuf[MAXAPIDS * 2 * 10 + 10]; // 2: Apids and Dpids, 10: 5 digits plus delimiting ',' or ';' plus optional '=cod', +10: paranoia
+ char apidbuf[(MAXAPIDS + MAXDPIDS) * 10 + 10]; // 10: 5 digits plus delimiting ',' or ';' plus optional '=cod', +10: paranoia
q = apidbuf;
q += IntArrayToString(q, Channel->apids, 10, Channel->alangs);
if (Channel->dpids[0]) {
@@ -726,7 +729,7 @@ bool cChannel::Parse(const char *s, bool AllowNonUniqueID)
int NumDpids = 0;
char *strtok_next;
while ((q = strtok_r(p, ",", &strtok_next)) != NULL) {
- if (NumDpids < MAXAPIDS) {
+ if (NumDpids < MAXDPIDS) {
char *l = strchr(q, '=');
if (l) {
*l++ = 0;
diff --git a/channels.h b/channels.h
index 3670ad36..472003f4 100644
--- a/channels.h
+++ b/channels.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: channels.h 1.24 2004/12/26 12:15:52 kls Exp $
+ * $Id: channels.h 1.25 2005/01/16 13:46:41 kls Exp $
*/
#ifndef __CHANNELS_H
@@ -30,8 +30,10 @@
#define CHANNELSMOD_AUTO 1
#define CHANNELSMOD_USER 2
-#define MAXAPIDS 32
-#define MAXCAIDS 8
+#define MAXAPIDS 32 // audio
+#define MAXDPIDS 8 // dolby
+#define MAXSPIDS 8 // subtitles
+#define MAXCAIDS 8 // conditional access
struct tChannelParameterMap {
int userValue;
@@ -100,8 +102,10 @@ private:
int ppid;
int apids[MAXAPIDS + 1]; // list is zero-terminated
char alangs[MAXAPIDS][4];
- int dpids[MAXAPIDS + 1]; // list is zero-terminated
- char dlangs[MAXAPIDS][4];
+ int dpids[MAXDPIDS + 1]; // list is zero-terminated
+ char dlangs[MAXDPIDS][4];
+ int spids[MAXSPIDS + 1]; // list is zero-terminated
+ char slangs[MAXSPIDS][4];
int tpid;
int caids[MAXCAIDS + 1]; // list is zero-terminated
int nid;
@@ -144,10 +148,15 @@ public:
int Srate(void) const { return srate; }
int Vpid(void) const { return vpid; }
int Ppid(void) const { return ppid; }
+ const int *Apids(void) const { return apids; }
+ const int *Dpids(void) const { return dpids; }
+ const int *Spids(void) const { return spids; }
int Apid(int i) const { return (0 <= i && i < MAXAPIDS) ? apids[i] : 0; }
- int Dpid(int i) const { return (0 <= i && i < MAXAPIDS) ? dpids[i] : 0; }
+ int Dpid(int i) const { return (0 <= i && i < MAXDPIDS) ? dpids[i] : 0; }
+ int Spid(int i) const { return (0 <= i && i < MAXSPIDS) ? spids[i] : 0; }
const char *Alang(int i) const { return (0 <= i && i < MAXAPIDS) ? alangs[i] : ""; }
- const char *Dlang(int i) const { return (0 <= i && i < MAXAPIDS) ? dlangs[i] : ""; }
+ const char *Dlang(int i) const { return (0 <= i && i < MAXDPIDS) ? dlangs[i] : ""; }
+ const char *Slang(int i) const { return (0 <= i && i < MAXSPIDS) ? slangs[i] : ""; }
int Tpid(void) const { return tpid; }
int Ca(int Index = 0) const { return Index < MAXCAIDS ? caids[Index] : 0; }
int Nid(void) const { return nid; }
diff --git a/device.c b/device.c
index 9e60b70b..0bbf21ce 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.73 2005/01/09 12:36:48 kls Exp $
+ * $Id: device.c 1.74 2005/01/16 14:05:37 kls Exp $
*/
#include "device.h"
@@ -512,7 +512,7 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
if (CaDevice && CanReplay()) {
cStatus::MsgChannelSwitch(this, 0); // only report status if we are actually going to switch the channel
if (CaDevice->SetChannel(Channel, false) == scrOk) // calling SetChannel() directly, not SwitchChannel()!
- cControl::Launch(new cTransferControl(CaDevice, Channel->Vpid(), Channel->Apid(0), Channel->Apid(1), Channel->Dpid(0), Channel->Dpid(1)));
+ cControl::Launch(new cTransferControl(CaDevice, Channel->Vpid(), Channel->Apids(), Channel->Dpids(), Channel->Spids()));
else
Result = scrNoTransfer;
}
@@ -545,11 +545,12 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
// Set the available audio tracks:
ClrAvailableTracks();
currentAudioTrack = ttAudioFirst;
- for (int i = 0; i < MAXAPIDS; i++) {
+ for (int i = 0; i < MAXAPIDS; i++)
SetAvailableTrack(ttAudio, i, Channel->Apid(i), Channel->Alang(i));
- if (Setup.UseDolbyDigital)
+ if (Setup.UseDolbyDigital) {
+ for (int i = 0; i < MAXDPIDS; i++)
SetAvailableTrack(ttDolby, i, Channel->Dpid(i), Channel->Dlang(i));
- }
+ }
// Select the preferred audio track:
eTrackType PreferredTrack = ttAudioFirst;
int LanguagePreference = -1;
@@ -849,7 +850,7 @@ int cDevice::PlayPesPacket(const uchar *Data, int Length, bool VideoOnly)
}
if (w > 0)
Start += w;
- else if (w <= 0) {
+ else {
if (Start != Data)
esyslog("ERROR: incomplete PES packet write!");
return Start == Data ? w : Start - Data;
@@ -1041,7 +1042,7 @@ bool cDevice::AttachReceiver(cReceiver *Receiver)
cMutexLock MutexLock(&mutexReceiver);
for (int i = 0; i < MAXRECEIVERS; i++) {
if (!receiver[i]) {
- for (int n = 0; n < MAXRECEIVEPIDS; n++) {
+ for (int n = 0; n < Receiver->numPids; n++) {
if (!AddPid(Receiver->pids[n])) {
for ( ; n-- > 0; )
DelPid(Receiver->pids[n]);
@@ -1074,7 +1075,7 @@ void cDevice::Detach(cReceiver *Receiver)
receiver[i] = NULL;
Receiver->device = NULL;
Unlock();
- for (int n = 0; n < MAXRECEIVEPIDS; n++)
+ for (int n = 0; n < Receiver->numPids; n++)
DelPid(Receiver->pids[n]);
}
else if (receiver[i])
diff --git a/device.h b/device.h
index 4a9e64ea..f04ba509 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.51 2005/01/08 10:15:00 kls Exp $
+ * $Id: device.h 1.52 2005/01/16 14:26:16 kls Exp $
*/
#ifndef __DEVICE_H
@@ -22,7 +22,7 @@
#include "tools.h"
#define MAXDEVICES 16 // the maximum number of devices in the system
-#define MAXPIDHANDLES 16 // the maximum number of different PIDs per device
+#define MAXPIDHANDLES 64 // the maximum number of different PIDs per device
#define MAXRECEIVERS 16 // the maximum number of receivers per device
#define MAXVOLUME 255
#define VOLUMEDELTA 5 // used to increase/decrease the volume
@@ -59,14 +59,14 @@ enum eVideoSystem { vsPAL,
enum eTrackType { ttNone,
ttAudio,
ttAudioFirst = ttAudio,
- ttAudioLast = ttAudioFirst + 31/*XXX MAXAPIDS - 1*/,
+ ttAudioLast = ttAudioFirst + 31, // MAXAPIDS - 1
ttDolby,
ttDolbyFirst = ttDolby,
- ttDolbyLast = ttDolbyFirst + 31/*XXX MAXAPIDS - 1*/,
+ ttDolbyLast = ttDolbyFirst + 8, // MAXDPIDS - 1
/* future...
ttSubtitle,
ttSubtitleFirst = ttSubtitle,
- ttSubtitleLast = ttSubtitleFirst + 31,
+ ttSubtitleLast = ttSubtitleFirst + 8, // MAXSPIDS - 1
*/
ttMaxTrackTypes
};
diff --git a/dvbdevice.c b/dvbdevice.c
index 3a7d3264..e8862cb4 100644
--- a/dvbdevice.c
+++ b/dvbdevice.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: dvbdevice.c 1.115 2005/01/16 11:59:21 kls Exp $
+ * $Id: dvbdevice.c 1.116 2005/01/16 12:05:13 kls Exp $
*/
#include "dvbdevice.h"
@@ -813,7 +813,7 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, true));
}
else if (StartTransferMode)
- cControl::Launch(new cTransferControl(this, Channel->Vpid(), Channel->Apid(0), Channel->Apid(1), Channel->Dpid(0), Channel->Dpid(1)));
+ cControl::Launch(new cTransferControl(this, Channel->Vpid(), Channel->Apids(), Channel->Dpids(), Channel->Spids()));
return true;
}
diff --git a/menu.c b/menu.c
index c8a28340..aac472da 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.336 2005/01/14 14:27:29 kls Exp $
+ * $Id: menu.c 1.337 2005/01/16 12:05:13 kls Exp $
*/
#include "menu.h"
@@ -3019,7 +3019,7 @@ cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer, bool Pause)
isyslog("record %s", fileName);
if (MakeDirs(fileName, true)) {
const cChannel *ch = timer->Channel();
- recorder = new cRecorder(fileName, ch->Ca(), timer->Priority(), ch->Vpid(), ch->Apid(0), ch->Apid(1), ch->Dpid(0), ch->Dpid(1));
+ recorder = new cRecorder(fileName, ch->Ca(), timer->Priority(), ch->Vpid(), ch->Apids(), ch->Dpids(), ch->Spids());
if (device->AttachReceiver(recorder)) {
Recording.WriteSummary();
cStatus::MsgRecording(device, Recording.Name());
diff --git a/pat.c b/pat.c
index a0124f7b..48ea715f 100644
--- a/pat.c
+++ b/pat.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: pat.c 1.10 2004/10/16 10:01:12 kls Exp $
+ * $Id: pat.c 1.11 2005/01/16 13:54:34 kls Exp $
*/
#include "pat.h"
@@ -325,9 +325,9 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
int Vpid = 0;
int Ppid = pmt.getPCRPid();
int Apids[MAXAPIDS] = { 0 };
- int Dpids[MAXAPIDS] = { 0 };
+ int Dpids[MAXDPIDS] = { 0 };
char ALangs[MAXAPIDS][4] = { "" };
- char DLangs[MAXAPIDS][4] = { "" };
+ char DLangs[MAXDPIDS][4] = { "" };
int Tpid = 0;
int NumApids = 0;
int NumDpids = 0;
@@ -386,7 +386,7 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
delete d;
}
if (dpid) {
- if (NumDpids < MAXAPIDS) {
+ if (NumDpids < MAXDPIDS) {
Dpids[NumDpids] = dpid;
strn0cpy(DLangs[NumDpids], lang, 4);
NumDpids++;
diff --git a/receiver.c b/receiver.c
index e9efac15..2fc36c9f 100644
--- a/receiver.c
+++ b/receiver.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: receiver.c 1.3 2002/07/28 15:14:49 kls Exp $
+ * $Id: receiver.c 1.4 2005/01/16 14:03:01 kls Exp $
*/
#include
@@ -12,25 +12,28 @@
#include "receiver.h"
#include "tools.h"
-cReceiver::cReceiver(int Ca, int Priority, int NumPids, ...)
+cReceiver::cReceiver(int Ca, int Priority, int Pid, const int *Pids1, const int *Pids2, const int *Pids3)
{
device = NULL;
ca = Ca;
priority = Priority;
- for (int i = 0; i < MAXRECEIVEPIDS; i++)
- pids[i] = 0;
- if (NumPids) {
- va_list ap;
- va_start(ap, NumPids);
- int n = 0;
- while (n < MAXRECEIVEPIDS && NumPids--) {
- if ((pids[n] = va_arg(ap, int)) != 0)
- n++;
- }
- va_end(ap);
+ numPids = 0;
+ if (Pid)
+ pids[numPids++] = Pid;
+ if (Pids1) {
+ while (*Pids1 && numPids < MAXRECEIVEPIDS)
+ pids[numPids++] = *Pids1++;
}
- else
- esyslog("ERROR: cReceiver called without a PID!");
+ if (Pids2) {
+ while (*Pids2 && numPids < MAXRECEIVEPIDS)
+ pids[numPids++] = *Pids2++;
+ }
+ if (Pids3) {
+ while (*Pids3 && numPids < MAXRECEIVEPIDS)
+ pids[numPids++] = *Pids3++;
+ }
+ if (numPids >= MAXRECEIVEPIDS)
+ dsyslog("too many PIDs in cReceiver");
}
cReceiver::~cReceiver()
@@ -41,11 +44,9 @@ cReceiver::~cReceiver()
bool cReceiver::WantsPid(int Pid)
{
if (Pid) {
- for (int i = 0; i < MAXRECEIVEPIDS; i++) {
+ for (int i = 0; i < numPids; i++) {
if (pids[i] == Pid)
return true;
- if (!pids[i])
- break;
}
}
return false;
diff --git a/receiver.h b/receiver.h
index 8ad8bc06..959f6d61 100644
--- a/receiver.h
+++ b/receiver.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: receiver.h 1.2 2002/07/28 11:22:01 kls Exp $
+ * $Id: receiver.h 1.3 2005/01/16 14:05:10 kls Exp $
*/
#ifndef __RECEIVER_H
@@ -12,7 +12,7 @@
#include "device.h"
-#define MAXRECEIVEPIDS 16 // the maximum number of PIDs per receiver
+#define MAXRECEIVEPIDS 64 // the maximum number of PIDs per receiver
class cReceiver {
friend class cDevice;
@@ -21,30 +21,32 @@ private:
int ca;
int priority;
int pids[MAXRECEIVEPIDS];
+ int numPids;
bool WantsPid(int Pid);
protected:
void Detach(void);
virtual void Activate(bool On) {}
- // This function is called just before the cReceiver gets attached to
- // (On == true) or detached from (On == false) a cDevice. It can be used
- // to do things like starting/stopping a thread.
- // It is guaranteed that Receive() will not be called before Activate(true).
+ ///< This function is called just before the cReceiver gets attached to
+ ///< (On == true) or detached from (On == false) a cDevice. It can be used
+ ///< to do things like starting/stopping a thread.
+ ///< It is guaranteed that Receive() will not be called before Activate(true).
virtual void Receive(uchar *Data, int Length) = 0;
- // This function is called from the cDevice we are attached to, and
- // delivers one TS packet from the set of PIDs the cReceiver has requested.
- // The data packet must be accepted immediately, and the call must return
- // as soon as possible, without any unnecessary delay. Each TS packet
- // will be delivered only ONCE, so the cReceiver must make sure that
- // it will be able to buffer the data if necessary.
+ ///< This function is called from the cDevice we are attached to, and
+ ///< delivers one TS packet from the set of PIDs the cReceiver has requested.
+ ///< The data packet must be accepted immediately, and the call must return
+ ///< as soon as possible, without any unnecessary delay. Each TS packet
+ ///< will be delivered only ONCE, so the cReceiver must make sure that
+ ///< it will be able to buffer the data if necessary.
public:
- cReceiver(int Ca, int Priority, int NumPids, ...);
- // Creates a new receiver that requires conditional access Ca and has
- // the given Priority. NumPids defines the number of PIDs that follow
- // this parameter. If any of these PIDs are 0, they will be silently ignored.
- // The total number of non-zero PIDs must not exceed MAXRECEIVEPIDS.
- // Priority may be any value in the range 0..99. Negative values indicate
- // that this cReceiver may be detached at any time (without blocking the
- // cDevice it is attached to).
+ cReceiver(int Ca, int Priority, int Pid, const int *Pids1 = NULL, const int *Pids2 = NULL, const int *Pids3 = NULL);
+ ///< Creates a new receiver that requires conditional access Ca and has
+ ///< the given Priority. Pid is a single PID (typically the video PID), while
+ ///< Pids1...Pids3 are pointers to zero terminated lists of PIDs.
+ ///< If any of these PIDs are 0, they will be silently ignored.
+ ///< The total number of non-zero PIDs must not exceed MAXRECEIVEPIDS.
+ ///< Priority may be any value in the range 0..99. Negative values indicate
+ ///< that this cReceiver may be detached at any time (without blocking the
+ ///< cDevice it is attached to).
virtual ~cReceiver();
};
diff --git a/recorder.c b/recorder.c
index ded60e8c..dd3f4f60 100644
--- a/recorder.c
+++ b/recorder.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: recorder.c 1.12 2005/01/09 12:16:36 kls Exp $
+ * $Id: recorder.c 1.13 2005/01/16 12:53:17 kls Exp $
*/
#include
@@ -127,8 +127,8 @@ void cFileWriter::Action(void)
active = false;
}
-cRecorder::cRecorder(const char *FileName, int Ca, int Priority, int VPid, int APid1, int APid2, int DPid1, int DPid2)
-:cReceiver(Ca, Priority, Setup.UseDolbyDigital ? 5 : 3, VPid, APid1, APid2, DPid1, DPid2)
+cRecorder::cRecorder(const char *FileName, int Ca, int Priority, int VPid, const int *APids, const int *DPids, const int *SPids)
+:cReceiver(Ca, Priority, VPid, APids, Setup.UseDolbyDigital ? DPids : NULL, SPids)
,cThread("recording")
{
active = false;
@@ -139,7 +139,7 @@ cRecorder::cRecorder(const char *FileName, int Ca, int Priority, int VPid, int A
ringBuffer = new cRingBufferLinear(RECORDERBUFSIZE, TS_SIZE * 2, true, "Recorder");
ringBuffer->SetTimeouts(0, 100);
- remux = new cRemux(VPid, APid1, APid2, DPid1, DPid2, true);
+ remux = new cRemux(VPid, APids, Setup.UseDolbyDigital ? DPids : NULL, SPids, true);
writer = new cFileWriter(FileName, remux);
}
diff --git a/recorder.h b/recorder.h
index 2a0875dd..da7934bf 100644
--- a/recorder.h
+++ b/recorder.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: recorder.h 1.2 2004/10/10 11:22:38 kls Exp $
+ * $Id: recorder.h 1.3 2005/01/16 12:05:13 kls Exp $
*/
#ifndef __RECORDER_H
@@ -29,7 +29,7 @@ protected:
virtual void Receive(uchar *Data, int Length);
virtual void Action(void);
public:
- cRecorder(const char *FileName, int Ca, int Priority, int VPid, int APid1, int APid2, int DPid1, int DPid2);
+ cRecorder(const char *FileName, int Ca, int Priority, int VPid, const int *APids, const int *DPids, const int *SPids);
// Creates a new recorder that requires conditional access Ca, has
// the given Priority and will record the given PIDs into the file FileName.
virtual ~cRecorder();
diff --git a/remux.c b/remux.c
index dc31c1af..e81909b5 100644
--- a/remux.c
+++ b/remux.c
@@ -11,11 +11,12 @@
* The cDolbyRepacker code was originally written by Reinhard Nissl ,
* and adapted to the VDR coding style by Klaus.Schmidinger@cadsoft.de.
*
- * $Id: remux.c 1.24 2005/01/15 12:07:43 kls Exp $
+ * $Id: remux.c 1.25 2005/01/16 14:34:25 kls Exp $
*/
#include "remux.h"
#include
+#include "channels.h"
#include "thread.h"
#include "tools.h"
@@ -335,6 +336,7 @@ int cDolbyRepacker::BreakAt(const uchar *Data, int Count)
class cTS2PES {
private:
+ int pid;
int size;
int found;
int count;
@@ -362,16 +364,18 @@ private:
void write_ipack(const uint8_t *Data, int Count);
void instant_repack(const uint8_t *Buf, int Count);
public:
- cTS2PES(cRingBufferLinear *ResultBuffer, int Size, uint8_t AudioCid = 0x00, cRepacker *Repacker = NULL);
+ cTS2PES(int Pid, cRingBufferLinear *ResultBuffer, int Size, uint8_t AudioCid = 0x00, cRepacker *Repacker = NULL);
~cTS2PES();
+ int Pid(void) { return pid; }
void ts_to_pes(const uint8_t *Buf); // don't need count (=188)
void Clear(void);
};
uint8_t cTS2PES::headr[] = { 0x00, 0x00, 0x01 };
-cTS2PES::cTS2PES(cRingBufferLinear *ResultBuffer, int Size, uint8_t AudioCid, cRepacker *Repacker)
+cTS2PES::cTS2PES(int Pid, cRingBufferLinear *ResultBuffer, int Size, uint8_t AudioCid, cRepacker *Repacker)
{
+ pid = Pid;
resultBuffer = ResultBuffer;
size = Size;
audioCid = AudioCid;
@@ -700,35 +704,44 @@ void cTS2PES::ts_to_pes(const uint8_t *Buf) // don't need count (=188)
#define RESULTBUFFERSIZE KILOBYTE(256)
-cRemux::cRemux(int VPid, int APid1, int APid2, int DPid1, int DPid2, bool ExitOnFailure)
+cRemux::cRemux(int VPid, const int *APids, const int *DPids, const int *SPids, bool ExitOnFailure)
{
- vPid = VPid;
- aPid1 = APid1;
- aPid2 = APid2;
- dPid1 = DPid1;
- dPid2 = DPid2;
exitOnFailure = ExitOnFailure;
+ isRadio = VPid == 0 || VPid == 1 || VPid == 0x1FFF;
numUPTerrors = 0;
synced = false;
skipped = 0;
+ numTracks = 0;
resultSkipped = 0;
resultBuffer = new cRingBufferLinear(RESULTBUFFERSIZE, IPACKS, false, "Result");
resultBuffer->SetTimeouts(0, 100);
- vTS2PES = new cTS2PES(resultBuffer, IPACKS);
- aTS2PES1 = new cTS2PES(resultBuffer, IPACKS, 0xC0);
- aTS2PES2 = aPid2 ? new cTS2PES(resultBuffer, IPACKS, 0xC1) : NULL;
- dTS2PES1 = dPid1 ? new cTS2PES(resultBuffer, IPACKS, 0x00, new cDolbyRepacker) : NULL;
- //XXX don't yet know how to tell apart primary and secondary DD data...
- dTS2PES2 = /*XXX dPid2 ? new cTS2PES(resultBuffer, IPACKS, 0x00, new cDolbyRepacker) : XXX*/ NULL;
+ if (VPid)
+ ts2pes[numTracks++] = new cTS2PES(VPid, resultBuffer, IPACKS);
+ if (APids) {
+ int n = 0;
+ while (*APids && numTracks < MAXTRACKS && n < MAXAPIDS)
+ ts2pes[numTracks++] = new cTS2PES(*APids++, resultBuffer, IPACKS, 0xC0 + n++);
+ }
+ if (DPids) {
+ int n = 0;
+ while (*DPids && numTracks < MAXTRACKS && n < MAXDPIDS) {
+ ts2pes[numTracks++] = new cTS2PES(*DPids++, resultBuffer, IPACKS, 0x00, new cDolbyRepacker); //XXX substream id(n++)???
+ break; //XXX until we can handle substream ids we can only handle a single Dolby track
+ }
+ }
+ /* future...
+ if (SPids) {
+ int n = 0;
+ while (*SPids && numTracks < MAXTRACKS && n < MAXSPIDS)
+ ts2pes[numTracks++] = new cTS2PES(*SPids++, resultBuffer, IPACKS); //XXX substream id(n++)???
+ }
+ */
}
cRemux::~cRemux()
{
- delete vTS2PES;
- delete aTS2PES1;
- delete aTS2PES2;
- delete dTS2PES1;
- delete dTS2PES2;
+ for (int t = 0; t < numTracks; t++)
+ delete ts2pes[t];
delete resultBuffer;
}
@@ -800,11 +813,12 @@ int cRemux::Put(const uchar *Data, int Count)
break; // A cTS2PES might write one full packet and also a small rest
int pid = GetPid(Data + i + 1);
if (Data[i + 3] & 0x10) { // got payload
- if (pid == vPid) vTS2PES->ts_to_pes(Data + i);
- else if (pid == aPid1) aTS2PES1->ts_to_pes(Data + i);
- else if (pid == aPid2 && aTS2PES2) aTS2PES2->ts_to_pes(Data + i);
- else if (pid == dPid1 && dTS2PES1) dTS2PES1->ts_to_pes(Data + i);
- else if (pid == dPid2 && dTS2PES2) dTS2PES2->ts_to_pes(Data + i);
+ for (int t = 0; t < numTracks; t++) {
+ if (ts2pes[t]->Pid() == pid) {
+ ts2pes[t]->ts_to_pes(Data + i);
+ break;
+ }
+ }
}
used += TS_SIZE;
}
@@ -842,7 +856,7 @@ uchar *cRemux::Get(int &Count, uchar *PictureType)
// Special VPID case to enable recording radio channels:
- if (vPid == 0 || vPid == 1 || vPid == 0x1FFF) {
+ if (isRadio) {
// XXX actually '0' should be enough, but '1' must be used with encrypted channels (driver bug?)
// XXX also allowing 0x1FFF to not break Michael Paar's original patch,
// XXX but it would probably be best to only use '0'
@@ -920,11 +934,8 @@ void cRemux::Del(int Count)
void cRemux::Clear(void)
{
- if (vTS2PES) vTS2PES->Clear();
- if (aTS2PES1) aTS2PES1->Clear();
- if (aTS2PES2) aTS2PES2->Clear();
- if (dTS2PES1) dTS2PES1->Clear();
- if (dTS2PES2) dTS2PES2->Clear();
+ for (int t = 0; t < numTracks; t++)
+ ts2pes[t]->Clear();
resultBuffer->Clear();
}
diff --git a/remux.h b/remux.h
index 0475c012..fef5980e 100644
--- a/remux.h
+++ b/remux.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: remux.h 1.12 2004/10/15 12:31:16 kls Exp $
+ * $Id: remux.h 1.13 2005/01/16 13:15:17 kls Exp $
*/
#ifndef __REMUX_H
@@ -21,23 +21,31 @@
#define P_FRAME 2
#define B_FRAME 3
+#define MAXTRACKS 64
+
class cTS2PES;
class cRemux {
private:
bool exitOnFailure;
+ bool isRadio;
int numUPTerrors;
bool synced;
int skipped;
- int vPid, aPid1, aPid2, dPid1, dPid2;
- cTS2PES *vTS2PES, *aTS2PES1, *aTS2PES2, *dTS2PES1, *dTS2PES2;
+ cTS2PES *ts2pes[MAXTRACKS];
+ int numTracks;
cRingBufferLinear *resultBuffer;
int resultSkipped;
int GetPid(const uchar *Data);
int GetPacketLength(const uchar *Data, int Count, int Offset);
int ScanVideoPacket(const uchar *Data, int Count, int Offset, uchar &PictureType);
public:
- cRemux(int VPid, int APid1, int APid2, int DPid1, int DPid2, bool ExitOnFailure = false);
+ cRemux(int VPid, const int *APids, const int *DPids, const int *SPids, bool ExitOnFailure = false);
+ ///< Creates a new remuxer for the given PIDs. VPid is the video PID, while
+ ///< APids, DPids and SPids are pointers to zero terminated lists of audio,
+ ///< dolby and subtitle PIDs (the pointers may be NULL if there is no such
+ ///< PID). If ExitOnFailure is true, the remuxer will initiate an "emergency
+ ///< exit" in case of problems with the data stream.
~cRemux();
int Put(const uchar *Data, int Count);
///< Puts at most Count bytes of Data into the remuxer.
diff --git a/transfer.c b/transfer.c
index 4a54da4f..537bb8f7 100644
--- a/transfer.c
+++ b/transfer.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: transfer.c 1.22 2005/01/07 15:44:30 kls Exp $
+ * $Id: transfer.c 1.23 2005/01/16 13:26:38 kls Exp $
*/
#include "transfer.h"
@@ -14,13 +14,13 @@
// --- cTransfer -------------------------------------------------------------
-cTransfer::cTransfer(int VPid, int APid1, int APid2, int DPid1, int DPid2)
-:cReceiver(0, -1, 5, VPid, APid1, APid2, DPid1, DPid2)
+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, APid1, APid2, DPid1, DPid2);
- needsBufferReserve = VPid != 0 && DPid1 != 0;
+ remux = new cRemux(VPid, APids, Setup.UseDolbyDigital ? DPids : NULL, SPids);
+ needsBufferReserve = Setup.UseDolbyDigital && VPid != 0 && DPids && DPids[0] != 0;
active = false;
}
@@ -143,8 +143,8 @@ void cTransfer::Action(void)
cDevice *cTransferControl::receiverDevice = NULL;
-cTransferControl::cTransferControl(cDevice *ReceiverDevice, int VPid, int APid1, int APid2, int DPid1, int DPid2)
-:cControl(transfer = new cTransfer(VPid, APid1, APid2, DPid1, DPid2), true)
+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;
diff --git a/transfer.h b/transfer.h
index bbe53a5b..377ecbef 100644
--- a/transfer.h
+++ b/transfer.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: transfer.h 1.8 2005/01/07 15:44:32 kls Exp $
+ * $Id: transfer.h 1.9 2005/01/16 12:05:13 kls Exp $
*/
#ifndef __TRANSFER_H
@@ -27,7 +27,7 @@ protected:
virtual void Receive(uchar *Data, int Length);
virtual void Action(void);
public:
- cTransfer(int VPid, int APid1, int APid2, int DPid1, int DPid2);
+ cTransfer(int VPid, const int *APids, const int *DPids, const int *SPids);
virtual ~cTransfer();
};
@@ -36,7 +36,7 @@ private:
cTransfer *transfer;
static cDevice *receiverDevice;
public:
- cTransferControl(cDevice *ReceiverDevice, int VPid, int APid1, int APid2, int DPid1, int DPid2);
+ cTransferControl(cDevice *ReceiverDevice, int VPid, const int *APids, const int *DPids, const int *SPids);
~cTransferControl();
virtual void Hide(void) {}
static cDevice *ReceiverDevice(void) { return receiverDevice; }
diff --git a/vdr.5 b/vdr.5
index 44ea3e68..1bc7db4b 100644
--- a/vdr.5
+++ b/vdr.5
@@ -8,7 +8,7 @@
.\" License as specified in the file COPYING that comes with the
.\" vdr distribution.
.\"
-.\" $Id: vdr.5 1.32 2005/01/09 13:16:40 kls Exp $
+.\" $Id: vdr.5 1.33 2005/01/16 13:45:57 kls Exp $
.\"
.TH vdr 5 "19 Dec 2004" "1.3.18" "Video Disk Recorder Files"
.SH NAME
@@ -559,7 +559,8 @@ The files \fI001.vdr\fR...\fI255.vdr\fR are the actual recorded MPEG data
files. In order to keep the size of an individual file below a given limit,
a recording is split into several files. The contents of these files is
\fBPacketized Elementary Stream\fR (PES) and contains ES packets with ids
-0xE0 for video, 0xC0 for audio 1 and 0xC1 for audio 2 (if available).
+0xE0...0xEF for video (only one of these may actually occur in a file),
+0xC0...0xDF for audio 1...32 (up to 32 audio tracks may occur).
Dolby Digital data is stored in packets with ids 0xBD.
.SS INDEX
The file \fIindex.vdr\fR (if present in a recording directory) contains
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|