1
0
mirror of https://github.com/VDR4Arch/vdr.git synced 2023-10-10 13:36:52 +02:00

Recording and Transfer Mode now handle more than 2 audio PIDs

This commit is contained in:
Klaus Schmidinger 2005-01-16 14:40:47 +01:00
parent 9423c636a2
commit c522225344
18 changed files with 184 additions and 145 deletions

View File

@ -3311,3 +3311,10 @@ Video Disk Recorder Revision History
- Fixed playing files with PES packets longer than 2048 byte through the full - Fixed playing files with PES packets longer than 2048 byte through the full
featured DVB card (thanks to Marco Kremer for reporting this one and providing featured DVB card (thanks to Marco Kremer for reporting this one and providing
a test sample). a test sample).
- Recording and Transfer Mode now handle more than 2 audio PIDs. For this the
interfaces of the following functions have been changed:
cTransferControl::cTransferControl()
cTransfer::cTransfer()
cRecorder::cRecorder()
cReceiver::cReceiver()
cRemux::cRemux()

View File

@ -14,18 +14,18 @@ Copyright &copy; 2004 Klaus Schmidinger<br>
<a href="http://www.cadsoft.de/vdr">www.cadsoft.de/vdr</a> <a href="http://www.cadsoft.de/vdr">www.cadsoft.de/vdr</a>
</center> </center>
<p> <p>
<!--X1.3.0--><table width=100%><tr><td bgcolor=#0000AA>&nbsp;</td><td width=100%> <!--X1.3.7--><table width=100%><tr><td bgcolor=#0000AA>&nbsp;</td><td width=100%>
Important modifications introduced in version 1.3.0 are marked like this.
<!--X1.3.0--></td></tr></table>
<!--X1.3.7--><table width=100%><tr><td bgcolor=#00AA00>&nbsp;</td><td width=100%>
Important modifications introduced in version 1.3.7 are marked like this. Important modifications introduced in version 1.3.7 are marked like this.
<!--X1.3.7--></td></tr></table> <!--X1.3.7--></td></tr></table>
<!--X1.3.8--><table width=100%><tr><td bgcolor=#AA0000>&nbsp;</td><td width=100%> <!--X1.3.8--><table width=100%><tr><td bgcolor=#00AA00>&nbsp;</td><td width=100%>
Important modifications introduced in version 1.3.8 are marked like this. Important modifications introduced in version 1.3.8 are marked like this.
<!--X1.3.8--></td></tr></table> <!--X1.3.8--></td></tr></table>
<!--X1.3.18--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%> <!--X1.3.18--><table width=100%><tr><td bgcolor=#AA0000>&nbsp;</td><td width=100%>
Important modifications introduced in version 1.3.18 are marked like this. Important modifications introduced in version 1.3.18 are marked like this.
<!--X1.3.18--></td></tr></table> <!--X1.3.18--></td></tr></table>
<!--X1.3.19--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%>
Important modifications introduced in version 1.3.19 are marked like this.
<!--X1.3.19--></td></tr></table>
<p> <p>
VDR provides an easy to use plugin interface that allows additional functionality 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. 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
<li><a href="#Status monitor">Status monitor</a> <li><a href="#Status monitor">Status monitor</a>
<li><a href="#Players">Players</a> <li><a href="#Players">Players</a>
<li><a href="#Receivers">Receivers</a> <li><a href="#Receivers">Receivers</a>
<!--X1.3.0--><table width=100%><tr><td bgcolor=#0000AA>&nbsp;</td><td width=100%>
<li><a href="#Filters">Filters</a> <li><a href="#Filters">Filters</a>
<!--X1.3.0--></td></tr></table>
<li><a href="#The On Screen Display">The On Screen Display</a> <li><a href="#The On Screen Display">The On Screen Display</a>
<!--X1.3.7--><table width=100%><tr><td bgcolor=#00AA00>&nbsp;</td><td width=100%> <!--X1.3.7--><table width=100%><tr><td bgcolor=#0000AA>&nbsp;</td><td width=100%>
<li><a href="#Skins">Skins</a> <li><a href="#Skins">Skins</a>
<li><a href="#Themes">Themes</a> <li><a href="#Themes">Themes</a>
<!--X1.3.7--></td></tr></table> <!--X1.3.7--></td></tr></table>
@ -1023,7 +1021,7 @@ public:
Take a look at the files <tt>player.h</tt> and <tt>dvbplayer.c</tt> to see how VDR implements Take a look at the files <tt>player.h</tt> and <tt>dvbplayer.c</tt> to see how VDR implements
its own player for the VDR recordings. its own player for the VDR recordings.
<p> <p>
<!--X1.3.18--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%> <!--X1.3.18--><table width=100%><tr><td bgcolor=#AA0000>&nbsp;</td><td width=100%>
To play the actual data, the player needs to call its member function To play the actual data, the player needs to call its member function
<p><table><tr><td bgcolor=#F0F0F0><pre> <p><table><tr><td bgcolor=#F0F0F0><pre>
@ -1046,7 +1044,7 @@ bool DevicePoll(cPoller &amp;Poller, int TimeoutMs = 0);
to determine whether the device is ready for further data. to determine whether the device is ready for further data.
<p> <p>
<!--X1.3.18--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%> <!--X1.3.18--><table width=100%><tr><td bgcolor=#AA0000>&nbsp;</td><td width=100%>
By default all audio track handling is done by the device a player is By default all audio track handling is done by the device a player is
attached to. attached to.
If the player can provide more than a single audio track, and has special If the player can provide more than a single audio track, and has special
@ -1183,7 +1181,9 @@ public:
}; };
cMyReceiver::cMyReceiver(int Pid) cMyReceiver::cMyReceiver(int Pid)
:cReceiver(0, -1, 1, Pid) <!--X1.3.19--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%>
:cReceiver(0, -1, Pid)
<!--X1.3.19--></td></tr></table>
{ {
} }
@ -1223,7 +1223,6 @@ Mode</i>).
If the <tt>cReceiver</tt> isn't needed any more, it may simply be <i>deleted</i> If the <tt>cReceiver</tt> isn't needed any more, it may simply be <i>deleted</i>
and will automatically detach itself from the <tt>cDevice</tt>. and will automatically detach itself from the <tt>cDevice</tt>.
<!--X1.3.0--><table width=100%><tr><td bgcolor=#0000AA>&nbsp;</td><td width=100%>
<a name="Filters"><hr><h2>Filters</h2> <a name="Filters"><hr><h2>Filters</h2>
<center><i><b>A Fistful of Datas</b></i></center><p> <center><i><b>A Fistful of Datas</b></i></center><p>
@ -1267,9 +1266,8 @@ If the <tt>cFilter</tt> isn't needed any more, it may simply be <i>deleted</i>
and will automatically detach itself from the <tt>cDevice</tt>. and will automatically detach itself from the <tt>cDevice</tt>.
<p> <p>
See VDR/eit.c or VDR/pat.c to learn how to process filter data. See VDR/eit.c or VDR/pat.c to learn how to process filter data.
<!--X1.3.0--></td></tr></table>
<!--X1.3.7--><table width=100%><tr><td bgcolor=#00AA00>&nbsp;</td><td width=100%> <!--X1.3.7--><table width=100%><tr><td bgcolor=#0000AA>&nbsp;</td><td width=100%>
<a name="The On Screen Display"><hr><h2>The On Screen Display</h2> <a name="The On Screen Display"><hr><h2>The On Screen Display</h2>
<center><i><b>Window to the world</b></i></center><p> <center><i><b>Window to the world</b></i></center><p>
@ -1362,7 +1360,7 @@ public:
virtual cSkinDisplayMenu *DisplayMenu(void); virtual cSkinDisplayMenu *DisplayMenu(void);
virtual cSkinDisplayReplay *DisplayReplay(bool ModeOnly); virtual cSkinDisplayReplay *DisplayReplay(bool ModeOnly);
virtual cSkinDisplayVolume *DisplayVolume(void); virtual cSkinDisplayVolume *DisplayVolume(void);
<!--X1.3.18--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%> <!--X1.3.18--><table width=100%><tr><td bgcolor=#AA0000>&nbsp;</td><td width=100%>
virtual cSkinDisplayMessage *DisplayTrack(int NumTracks, const char * const *Tracks); virtual cSkinDisplayMessage *DisplayTrack(int NumTracks, const char * const *Tracks);
<!--X1.3.18--></td></tr></table> <!--X1.3.18--></td></tr></table>
virtual cSkinDisplayMessage *DisplayMessage(void); virtual cSkinDisplayMessage *DisplayMessage(void);
@ -1384,7 +1382,7 @@ new cMySkin;
in the <a href="#Getting started"><tt>Start()</tt></a> function of your plugin. in the <a href="#Getting started"><tt>Start()</tt></a> function of your plugin.
Do not delete this object, it will be automatically deleted when the program ends. Do not delete this object, it will be automatically deleted when the program ends.
<p> <p>
<!--X1.3.8--><table width=100%><tr><td bgcolor=#AA0000>&nbsp;</td><td width=100%> <!--X1.3.8--><table width=100%><tr><td bgcolor=#00AA00>&nbsp;</td><td width=100%>
In order to be able to easily identify plugins that implement a skin it is recommended 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 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 If the device can provide more than a single audio track, it can implement the
following function to make them available: following function to make them available:
<!--X1.3.18--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%> <!--X1.3.18--><table width=100%><tr><td bgcolor=#AA0000>&nbsp;</td><td width=100%>
<p><table><tr><td bgcolor=#F0F0F0><pre> <p><table><tr><td bgcolor=#F0F0F0><pre>
virtual void SetAudioTrackDevice(eTrackType Type); virtual void SetAudioTrackDevice(eTrackType Type);
virtual int GetAudioChannelDevice(void); virtual int GetAudioChannelDevice(void);
@ -1558,7 +1556,6 @@ virtual void SetVideoFormat(bool VideoFormat16_9);
virtual void SetVolumeDevice(int Volume); virtual void SetVolumeDevice(int Volume);
</pre></td></tr></table><p> </pre></td></tr></table><p>
<!--X1.3.0--><table width=100%><tr><td bgcolor=#0000AA>&nbsp;</td><td width=100%>
<p> <p>
<b>Section Filtering</b> <b>Section Filtering</b>
<p> <p>
@ -1583,12 +1580,11 @@ from its constructor.
<p> <p>
See <a href="#Filters">Filters</a> on how to set up actual filters that can See <a href="#Filters">Filters</a> on how to set up actual filters that can
handle section data. handle section data.
<!--X1.3.0--></td></tr></table>
<p> <p>
<b>On Screen Display</b> <b>On Screen Display</b>
<p> <p>
<!--X1.3.7--><table width=100%><tr><td bgcolor=#00AA00>&nbsp;</td><td width=100%> <!--X1.3.7--><table width=100%><tr><td bgcolor=#0000AA>&nbsp;</td><td width=100%>
If your device provides On Screen Display (OSD) capabilities (which every device 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 that is supposed to be used as a primary device should do), it shall implement
an "OSD provider" class, derived from <tt>cOsdProvider</tt>, which, when its <tt>CreateOsd()</tt> an "OSD provider" class, derived from <tt>cOsdProvider</tt>, which, when its <tt>CreateOsd()</tt>

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "channels.h"
@ -193,6 +193,7 @@ cChannel::cChannel(const cChannel &Channel)
ppid = 0; ppid = 0;
apids[0] = 0; apids[0] = 0;
dpids[0] = 0; dpids[0] = 0;
spids[0] = 0;
tpid = 0; tpid = 0;
caids[0] = 0; caids[0] = 0;
nid = 0; nid = 0;
@ -421,8 +422,8 @@ void cChannel::SetPids(int Vpid, int Ppid, int *Apids, char ALangs[][4], int *Dp
if (!modified) if (!modified)
modified = IntArraysDiffer(apids, Apids, alangs, ALangs) || IntArraysDiffer(dpids, Dpids, dlangs, DLangs); modified = IntArraysDiffer(apids, Apids, alangs, ALangs) || IntArraysDiffer(dpids, Dpids, dlangs, DLangs);
if (modified) { if (modified) {
char OldApidsBuf[MAXAPIDS * 2 * 10 + 10]; // 2: Apids and Dpids, 10: 5 digits plus delimiting ',' or ';' plus optional '=cod', +10: paranoia char OldApidsBuf[(MAXAPIDS + MAXDPIDS) * 10 + 10]; // 10: 5 digits plus delimiting ',' or ';' plus optional '=cod', +10: paranoia
char NewApidsBuf[MAXAPIDS * 2 * 10 + 10]; char NewApidsBuf[(MAXAPIDS + MAXDPIDS) * 10 + 10];
char *q = OldApidsBuf; char *q = OldApidsBuf;
q += IntArrayToString(q, apids, 10, alangs); q += IntArrayToString(q, apids, 10, alangs);
if (dpids[0]) { 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 for (int i = 0; i <= MAXAPIDS; i++) { // <= to copy the terminating 0
apids[i] = Apids[i]; apids[i] = Apids[i];
strn0cpy(alangs[i], ALangs[i], 4); strn0cpy(alangs[i], ALangs[i], 4);
}
for (int i = 0; i <= MAXDPIDS; i++) { // <= to copy the terminating 0
dpids[i] = Dpids[i]; dpids[i] = Dpids[i];
strn0cpy(dlangs[i], DLangs[i], 4); strn0cpy(dlangs[i], DLangs[i], 4);
} }
@ -623,7 +626,7 @@ cString cChannel::ToText(const cChannel *Channel)
if (Channel->ppid && Channel->ppid != Channel->vpid) if (Channel->ppid && Channel->ppid != Channel->vpid)
q += snprintf(q, sizeof(vpidbuf) - (q - vpidbuf), "+%d", Channel->ppid); q += snprintf(q, sizeof(vpidbuf) - (q - vpidbuf), "+%d", Channel->ppid);
*q = 0; *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 = apidbuf;
q += IntArrayToString(q, Channel->apids, 10, Channel->alangs); q += IntArrayToString(q, Channel->apids, 10, Channel->alangs);
if (Channel->dpids[0]) { if (Channel->dpids[0]) {
@ -726,7 +729,7 @@ bool cChannel::Parse(const char *s, bool AllowNonUniqueID)
int NumDpids = 0; int NumDpids = 0;
char *strtok_next; char *strtok_next;
while ((q = strtok_r(p, ",", &strtok_next)) != NULL) { while ((q = strtok_r(p, ",", &strtok_next)) != NULL) {
if (NumDpids < MAXAPIDS) { if (NumDpids < MAXDPIDS) {
char *l = strchr(q, '='); char *l = strchr(q, '=');
if (l) { if (l) {
*l++ = 0; *l++ = 0;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __CHANNELS_H
@ -30,8 +30,10 @@
#define CHANNELSMOD_AUTO 1 #define CHANNELSMOD_AUTO 1
#define CHANNELSMOD_USER 2 #define CHANNELSMOD_USER 2
#define MAXAPIDS 32 #define MAXAPIDS 32 // audio
#define MAXCAIDS 8 #define MAXDPIDS 8 // dolby
#define MAXSPIDS 8 // subtitles
#define MAXCAIDS 8 // conditional access
struct tChannelParameterMap { struct tChannelParameterMap {
int userValue; int userValue;
@ -100,8 +102,10 @@ private:
int ppid; int ppid;
int apids[MAXAPIDS + 1]; // list is zero-terminated int apids[MAXAPIDS + 1]; // list is zero-terminated
char alangs[MAXAPIDS][4]; char alangs[MAXAPIDS][4];
int dpids[MAXAPIDS + 1]; // list is zero-terminated int dpids[MAXDPIDS + 1]; // list is zero-terminated
char dlangs[MAXAPIDS][4]; char dlangs[MAXDPIDS][4];
int spids[MAXSPIDS + 1]; // list is zero-terminated
char slangs[MAXSPIDS][4];
int tpid; int tpid;
int caids[MAXCAIDS + 1]; // list is zero-terminated int caids[MAXCAIDS + 1]; // list is zero-terminated
int nid; int nid;
@ -144,10 +148,15 @@ public:
int Srate(void) const { return srate; } int Srate(void) const { return srate; }
int Vpid(void) const { return vpid; } int Vpid(void) const { return vpid; }
int Ppid(void) const { return ppid; } 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 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 *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 Tpid(void) const { return tpid; }
int Ca(int Index = 0) const { return Index < MAXCAIDS ? caids[Index] : 0; } int Ca(int Index = 0) const { return Index < MAXCAIDS ? caids[Index] : 0; }
int Nid(void) const { return nid; } int Nid(void) const { return nid; }

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "device.h"
@ -512,7 +512,7 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
if (CaDevice && CanReplay()) { if (CaDevice && CanReplay()) {
cStatus::MsgChannelSwitch(this, 0); // only report status if we are actually going to switch the channel 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()! 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 else
Result = scrNoTransfer; Result = scrNoTransfer;
} }
@ -545,9 +545,10 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
// Set the available audio tracks: // Set the available audio tracks:
ClrAvailableTracks(); ClrAvailableTracks();
currentAudioTrack = ttAudioFirst; 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)); 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)); SetAvailableTrack(ttDolby, i, Channel->Dpid(i), Channel->Dlang(i));
} }
// Select the preferred audio track: // Select the preferred audio track:
@ -849,7 +850,7 @@ int cDevice::PlayPesPacket(const uchar *Data, int Length, bool VideoOnly)
} }
if (w > 0) if (w > 0)
Start += w; Start += w;
else if (w <= 0) { else {
if (Start != Data) if (Start != Data)
esyslog("ERROR: incomplete PES packet write!"); esyslog("ERROR: incomplete PES packet write!");
return Start == Data ? w : Start - Data; return Start == Data ? w : Start - Data;
@ -1041,7 +1042,7 @@ bool cDevice::AttachReceiver(cReceiver *Receiver)
cMutexLock MutexLock(&mutexReceiver); cMutexLock MutexLock(&mutexReceiver);
for (int i = 0; i < MAXRECEIVERS; i++) { for (int i = 0; i < MAXRECEIVERS; i++) {
if (!receiver[i]) { if (!receiver[i]) {
for (int n = 0; n < MAXRECEIVEPIDS; n++) { for (int n = 0; n < Receiver->numPids; n++) {
if (!AddPid(Receiver->pids[n])) { if (!AddPid(Receiver->pids[n])) {
for ( ; n-- > 0; ) for ( ; n-- > 0; )
DelPid(Receiver->pids[n]); DelPid(Receiver->pids[n]);
@ -1074,7 +1075,7 @@ void cDevice::Detach(cReceiver *Receiver)
receiver[i] = NULL; receiver[i] = NULL;
Receiver->device = NULL; Receiver->device = NULL;
Unlock(); Unlock();
for (int n = 0; n < MAXRECEIVEPIDS; n++) for (int n = 0; n < Receiver->numPids; n++)
DelPid(Receiver->pids[n]); DelPid(Receiver->pids[n]);
} }
else if (receiver[i]) else if (receiver[i])

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __DEVICE_H
@ -22,7 +22,7 @@
#include "tools.h" #include "tools.h"
#define MAXDEVICES 16 // the maximum number of devices in the system #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 MAXRECEIVERS 16 // the maximum number of receivers per device
#define MAXVOLUME 255 #define MAXVOLUME 255
#define VOLUMEDELTA 5 // used to increase/decrease the volume #define VOLUMEDELTA 5 // used to increase/decrease the volume
@ -59,14 +59,14 @@ enum eVideoSystem { vsPAL,
enum eTrackType { ttNone, enum eTrackType { ttNone,
ttAudio, ttAudio,
ttAudioFirst = ttAudio, ttAudioFirst = ttAudio,
ttAudioLast = ttAudioFirst + 31/*XXX MAXAPIDS - 1*/, ttAudioLast = ttAudioFirst + 31, // MAXAPIDS - 1
ttDolby, ttDolby,
ttDolbyFirst = ttDolby, ttDolbyFirst = ttDolby,
ttDolbyLast = ttDolbyFirst + 31/*XXX MAXAPIDS - 1*/, ttDolbyLast = ttDolbyFirst + 8, // MAXDPIDS - 1
/* future... /* future...
ttSubtitle, ttSubtitle,
ttSubtitleFirst = ttSubtitle, ttSubtitleFirst = ttSubtitle,
ttSubtitleLast = ttSubtitleFirst + 31, ttSubtitleLast = ttSubtitleFirst + 8, // MAXSPIDS - 1
*/ */
ttMaxTrackTypes ttMaxTrackTypes
}; };

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "dvbdevice.h"
@ -813,7 +813,7 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, true)); CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, true));
} }
else if (StartTransferMode) 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; return true;
} }

4
menu.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "menu.h"
@ -3019,7 +3019,7 @@ cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer, bool Pause)
isyslog("record %s", fileName); isyslog("record %s", fileName);
if (MakeDirs(fileName, true)) { if (MakeDirs(fileName, true)) {
const cChannel *ch = timer->Channel(); 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)) { if (device->AttachReceiver(recorder)) {
Recording.WriteSummary(); Recording.WriteSummary();
cStatus::MsgRecording(device, Recording.Name()); cStatus::MsgRecording(device, Recording.Name());

8
pat.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #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 Vpid = 0;
int Ppid = pmt.getPCRPid(); int Ppid = pmt.getPCRPid();
int Apids[MAXAPIDS] = { 0 }; int Apids[MAXAPIDS] = { 0 };
int Dpids[MAXAPIDS] = { 0 }; int Dpids[MAXDPIDS] = { 0 };
char ALangs[MAXAPIDS][4] = { "" }; char ALangs[MAXAPIDS][4] = { "" };
char DLangs[MAXAPIDS][4] = { "" }; char DLangs[MAXDPIDS][4] = { "" };
int Tpid = 0; int Tpid = 0;
int NumApids = 0; int NumApids = 0;
int NumDpids = 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; delete d;
} }
if (dpid) { if (dpid) {
if (NumDpids < MAXAPIDS) { if (NumDpids < MAXDPIDS) {
Dpids[NumDpids] = dpid; Dpids[NumDpids] = dpid;
strn0cpy(DLangs[NumDpids], lang, 4); strn0cpy(DLangs[NumDpids], lang, 4);
NumDpids++; NumDpids++;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 <stdarg.h> #include <stdarg.h>
@ -12,25 +12,28 @@
#include "receiver.h" #include "receiver.h"
#include "tools.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; device = NULL;
ca = Ca; ca = Ca;
priority = Priority; priority = Priority;
for (int i = 0; i < MAXRECEIVEPIDS; i++) numPids = 0;
pids[i] = 0; if (Pid)
if (NumPids) { pids[numPids++] = Pid;
va_list ap; if (Pids1) {
va_start(ap, NumPids); while (*Pids1 && numPids < MAXRECEIVEPIDS)
int n = 0; pids[numPids++] = *Pids1++;
while (n < MAXRECEIVEPIDS && NumPids--) {
if ((pids[n] = va_arg(ap, int)) != 0)
n++;
} }
va_end(ap); if (Pids2) {
while (*Pids2 && numPids < MAXRECEIVEPIDS)
pids[numPids++] = *Pids2++;
} }
else if (Pids3) {
esyslog("ERROR: cReceiver called without a PID!"); while (*Pids3 && numPids < MAXRECEIVEPIDS)
pids[numPids++] = *Pids3++;
}
if (numPids >= MAXRECEIVEPIDS)
dsyslog("too many PIDs in cReceiver");
} }
cReceiver::~cReceiver() cReceiver::~cReceiver()
@ -41,11 +44,9 @@ cReceiver::~cReceiver()
bool cReceiver::WantsPid(int Pid) bool cReceiver::WantsPid(int Pid)
{ {
if (Pid) { if (Pid) {
for (int i = 0; i < MAXRECEIVEPIDS; i++) { for (int i = 0; i < numPids; i++) {
if (pids[i] == Pid) if (pids[i] == Pid)
return true; return true;
if (!pids[i])
break;
} }
} }
return false; return false;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __RECEIVER_H
@ -12,7 +12,7 @@
#include "device.h" #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 { class cReceiver {
friend class cDevice; friend class cDevice;
@ -21,30 +21,32 @@ private:
int ca; int ca;
int priority; int priority;
int pids[MAXRECEIVEPIDS]; int pids[MAXRECEIVEPIDS];
int numPids;
bool WantsPid(int Pid); bool WantsPid(int Pid);
protected: protected:
void Detach(void); void Detach(void);
virtual void Activate(bool On) {} virtual void Activate(bool On) {}
// This function is called just before the cReceiver gets attached to ///< This function is called just before the cReceiver gets attached to
// (On == true) or detached from (On == false) a cDevice. It can be used ///< (On == true) or detached from (On == false) a cDevice. It can be used
// to do things like starting/stopping a thread. ///< to do things like starting/stopping a thread.
// It is guaranteed that Receive() will not be called before Activate(true). ///< It is guaranteed that Receive() will not be called before Activate(true).
virtual void Receive(uchar *Data, int Length) = 0; virtual void Receive(uchar *Data, int Length) = 0;
// This function is called from the cDevice we are attached to, and ///< 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. ///< 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 ///< The data packet must be accepted immediately, and the call must return
// as soon as possible, without any unnecessary delay. Each TS packet ///< as soon as possible, without any unnecessary delay. Each TS packet
// will be delivered only ONCE, so the cReceiver must make sure that ///< will be delivered only ONCE, so the cReceiver must make sure that
// it will be able to buffer the data if necessary. ///< it will be able to buffer the data if necessary.
public: public:
cReceiver(int Ca, int Priority, int NumPids, ...); 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 ///< Creates a new receiver that requires conditional access Ca and has
// the given Priority. NumPids defines the number of PIDs that follow ///< the given Priority. Pid is a single PID (typically the video PID), while
// this parameter. If any of these PIDs are 0, they will be silently ignored. ///< Pids1...Pids3 are pointers to zero terminated lists of PIDs.
// The total number of non-zero PIDs must not exceed MAXRECEIVEPIDS. ///< If any of these PIDs are 0, they will be silently ignored.
// Priority may be any value in the range 0..99. Negative values indicate ///< The total number of non-zero PIDs must not exceed MAXRECEIVEPIDS.
// that this cReceiver may be detached at any time (without blocking the ///< Priority may be any value in the range 0..99. Negative values indicate
// cDevice it is attached to). ///< that this cReceiver may be detached at any time (without blocking the
///< cDevice it is attached to).
virtual ~cReceiver(); virtual ~cReceiver();
}; };

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 <stdarg.h> #include <stdarg.h>
@ -127,8 +127,8 @@ void cFileWriter::Action(void)
active = false; active = false;
} }
cRecorder::cRecorder(const char *FileName, int Ca, int Priority, int VPid, int APid1, int APid2, int DPid1, int DPid2) cRecorder::cRecorder(const char *FileName, int Ca, int Priority, int VPid, const int *APids, const int *DPids, const int *SPids)
:cReceiver(Ca, Priority, Setup.UseDolbyDigital ? 5 : 3, VPid, APid1, APid2, DPid1, DPid2) :cReceiver(Ca, Priority, VPid, APids, Setup.UseDolbyDigital ? DPids : NULL, SPids)
,cThread("recording") ,cThread("recording")
{ {
active = false; 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 = new cRingBufferLinear(RECORDERBUFSIZE, TS_SIZE * 2, true, "Recorder");
ringBuffer->SetTimeouts(0, 100); 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); writer = new cFileWriter(FileName, remux);
} }

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __RECORDER_H
@ -29,7 +29,7 @@ protected:
virtual void Receive(uchar *Data, int Length); virtual void Receive(uchar *Data, int Length);
virtual void Action(void); virtual void Action(void);
public: 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 // Creates a new recorder that requires conditional access Ca, has
// the given Priority and will record the given PIDs into the file FileName. // the given Priority and will record the given PIDs into the file FileName.
virtual ~cRecorder(); virtual ~cRecorder();

73
remux.c
View File

@ -11,11 +11,12 @@
* The cDolbyRepacker code was originally written by Reinhard Nissl <rnissl@gmx.de>, * The cDolbyRepacker code was originally written by Reinhard Nissl <rnissl@gmx.de>,
* and adapted to the VDR coding style by Klaus.Schmidinger@cadsoft.de. * 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 "remux.h"
#include <stdlib.h> #include <stdlib.h>
#include "channels.h"
#include "thread.h" #include "thread.h"
#include "tools.h" #include "tools.h"
@ -335,6 +336,7 @@ int cDolbyRepacker::BreakAt(const uchar *Data, int Count)
class cTS2PES { class cTS2PES {
private: private:
int pid;
int size; int size;
int found; int found;
int count; int count;
@ -362,16 +364,18 @@ private:
void write_ipack(const uint8_t *Data, int Count); void write_ipack(const uint8_t *Data, int Count);
void instant_repack(const uint8_t *Buf, int Count); void instant_repack(const uint8_t *Buf, int Count);
public: 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(); ~cTS2PES();
int Pid(void) { return pid; }
void ts_to_pes(const uint8_t *Buf); // don't need count (=188) void ts_to_pes(const uint8_t *Buf); // don't need count (=188)
void Clear(void); void Clear(void);
}; };
uint8_t cTS2PES::headr[] = { 0x00, 0x00, 0x01 }; 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; resultBuffer = ResultBuffer;
size = Size; size = Size;
audioCid = AudioCid; audioCid = AudioCid;
@ -700,35 +704,44 @@ void cTS2PES::ts_to_pes(const uint8_t *Buf) // don't need count (=188)
#define RESULTBUFFERSIZE KILOBYTE(256) #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; exitOnFailure = ExitOnFailure;
isRadio = VPid == 0 || VPid == 1 || VPid == 0x1FFF;
numUPTerrors = 0; numUPTerrors = 0;
synced = false; synced = false;
skipped = 0; skipped = 0;
numTracks = 0;
resultSkipped = 0; resultSkipped = 0;
resultBuffer = new cRingBufferLinear(RESULTBUFFERSIZE, IPACKS, false, "Result"); resultBuffer = new cRingBufferLinear(RESULTBUFFERSIZE, IPACKS, false, "Result");
resultBuffer->SetTimeouts(0, 100); resultBuffer->SetTimeouts(0, 100);
vTS2PES = new cTS2PES(resultBuffer, IPACKS); if (VPid)
aTS2PES1 = new cTS2PES(resultBuffer, IPACKS, 0xC0); ts2pes[numTracks++] = new cTS2PES(VPid, resultBuffer, IPACKS);
aTS2PES2 = aPid2 ? new cTS2PES(resultBuffer, IPACKS, 0xC1) : NULL; if (APids) {
dTS2PES1 = dPid1 ? new cTS2PES(resultBuffer, IPACKS, 0x00, new cDolbyRepacker) : NULL; int n = 0;
//XXX don't yet know how to tell apart primary and secondary DD data... while (*APids && numTracks < MAXTRACKS && n < MAXAPIDS)
dTS2PES2 = /*XXX dPid2 ? new cTS2PES(resultBuffer, IPACKS, 0x00, new cDolbyRepacker) : XXX*/ NULL; 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() cRemux::~cRemux()
{ {
delete vTS2PES; for (int t = 0; t < numTracks; t++)
delete aTS2PES1; delete ts2pes[t];
delete aTS2PES2;
delete dTS2PES1;
delete dTS2PES2;
delete resultBuffer; 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 break; // A cTS2PES might write one full packet and also a small rest
int pid = GetPid(Data + i + 1); int pid = GetPid(Data + i + 1);
if (Data[i + 3] & 0x10) { // got payload if (Data[i + 3] & 0x10) { // got payload
if (pid == vPid) vTS2PES->ts_to_pes(Data + i); for (int t = 0; t < numTracks; t++) {
else if (pid == aPid1) aTS2PES1->ts_to_pes(Data + i); if (ts2pes[t]->Pid() == pid) {
else if (pid == aPid2 && aTS2PES2) aTS2PES2->ts_to_pes(Data + i); ts2pes[t]->ts_to_pes(Data + i);
else if (pid == dPid1 && dTS2PES1) dTS2PES1->ts_to_pes(Data + i); break;
else if (pid == dPid2 && dTS2PES2) dTS2PES2->ts_to_pes(Data + i); }
}
} }
used += TS_SIZE; used += TS_SIZE;
} }
@ -842,7 +856,7 @@ uchar *cRemux::Get(int &Count, uchar *PictureType)
// Special VPID case to enable recording radio channels: // 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 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 also allowing 0x1FFF to not break Michael Paar's original patch,
// XXX but it would probably be best to only use '0' // XXX but it would probably be best to only use '0'
@ -920,11 +934,8 @@ void cRemux::Del(int Count)
void cRemux::Clear(void) void cRemux::Clear(void)
{ {
if (vTS2PES) vTS2PES->Clear(); for (int t = 0; t < numTracks; t++)
if (aTS2PES1) aTS2PES1->Clear(); ts2pes[t]->Clear();
if (aTS2PES2) aTS2PES2->Clear();
if (dTS2PES1) dTS2PES1->Clear();
if (dTS2PES2) dTS2PES2->Clear();
resultBuffer->Clear(); resultBuffer->Clear();
} }

16
remux.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __REMUX_H
@ -21,23 +21,31 @@
#define P_FRAME 2 #define P_FRAME 2
#define B_FRAME 3 #define B_FRAME 3
#define MAXTRACKS 64
class cTS2PES; class cTS2PES;
class cRemux { class cRemux {
private: private:
bool exitOnFailure; bool exitOnFailure;
bool isRadio;
int numUPTerrors; int numUPTerrors;
bool synced; bool synced;
int skipped; int skipped;
int vPid, aPid1, aPid2, dPid1, dPid2; cTS2PES *ts2pes[MAXTRACKS];
cTS2PES *vTS2PES, *aTS2PES1, *aTS2PES2, *dTS2PES1, *dTS2PES2; int numTracks;
cRingBufferLinear *resultBuffer; cRingBufferLinear *resultBuffer;
int resultSkipped; int resultSkipped;
int GetPid(const uchar *Data); int GetPid(const uchar *Data);
int GetPacketLength(const uchar *Data, int Count, int Offset); int GetPacketLength(const uchar *Data, int Count, int Offset);
int ScanVideoPacket(const uchar *Data, int Count, int Offset, uchar &PictureType); int ScanVideoPacket(const uchar *Data, int Count, int Offset, uchar &PictureType);
public: 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(); ~cRemux();
int Put(const uchar *Data, int Count); int Put(const uchar *Data, int Count);
///< Puts at most Count bytes of Data into the remuxer. ///< Puts at most Count bytes of Data into the remuxer.

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "transfer.h"
@ -14,13 +14,13 @@
// --- cTransfer ------------------------------------------------------------- // --- cTransfer -------------------------------------------------------------
cTransfer::cTransfer(int VPid, int APid1, int APid2, int DPid1, int DPid2) cTransfer::cTransfer(int VPid, const int *APids, const int *DPids, const int *SPids)
:cReceiver(0, -1, 5, VPid, APid1, APid2, DPid1, DPid2) :cReceiver(0, -1, VPid, APids, Setup.UseDolbyDigital ? DPids : NULL, SPids)
,cThread("transfer") ,cThread("transfer")
{ {
ringBuffer = new cRingBufferLinear(TRANSFERBUFSIZE, TS_SIZE * 2, true, "Transfer"); ringBuffer = new cRingBufferLinear(TRANSFERBUFSIZE, TS_SIZE * 2, true, "Transfer");
remux = new cRemux(VPid, APid1, APid2, DPid1, DPid2); remux = new cRemux(VPid, APids, Setup.UseDolbyDigital ? DPids : NULL, SPids);
needsBufferReserve = VPid != 0 && DPid1 != 0; needsBufferReserve = Setup.UseDolbyDigital && VPid != 0 && DPids && DPids[0] != 0;
active = false; active = false;
} }
@ -143,8 +143,8 @@ void cTransfer::Action(void)
cDevice *cTransferControl::receiverDevice = NULL; cDevice *cTransferControl::receiverDevice = NULL;
cTransferControl::cTransferControl(cDevice *ReceiverDevice, int VPid, int APid1, int APid2, int DPid1, int DPid2) cTransferControl::cTransferControl(cDevice *ReceiverDevice, int VPid, const int *APids, const int *DPids, const int *SPids)
:cControl(transfer = new cTransfer(VPid, APid1, APid2, DPid1, DPid2), true) :cControl(transfer = new cTransfer(VPid, APids, DPids, SPids), true)
{ {
ReceiverDevice->AttachReceiver(transfer); ReceiverDevice->AttachReceiver(transfer);
receiverDevice = ReceiverDevice; receiverDevice = ReceiverDevice;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __TRANSFER_H
@ -27,7 +27,7 @@ protected:
virtual void Receive(uchar *Data, int Length); virtual void Receive(uchar *Data, int Length);
virtual void Action(void); virtual void Action(void);
public: 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(); virtual ~cTransfer();
}; };
@ -36,7 +36,7 @@ private:
cTransfer *transfer; cTransfer *transfer;
static cDevice *receiverDevice; static cDevice *receiverDevice;
public: 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(); ~cTransferControl();
virtual void Hide(void) {} virtual void Hide(void) {}
static cDevice *ReceiverDevice(void) { return receiverDevice; } static cDevice *ReceiverDevice(void) { return receiverDevice; }

5
vdr.5
View File

@ -8,7 +8,7 @@
.\" License as specified in the file COPYING that comes with the .\" License as specified in the file COPYING that comes with the
.\" vdr distribution. .\" 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" .TH vdr 5 "19 Dec 2004" "1.3.18" "Video Disk Recorder Files"
.SH NAME .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, 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 a recording is split into several files. The contents of these files is
\fBPacketized Elementary Stream\fR (PES) and contains ES packets with ids \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. Dolby Digital data is stored in packets with ids 0xBD.
.SS INDEX .SS INDEX
The file \fIindex.vdr\fR (if present in a recording directory) contains The file \fIindex.vdr\fR (if present in a recording directory) contains