The PCR pid is now recorded for channels where this is different from the video PID

This commit is contained in:
Klaus Schmidinger 2010-01-30 11:10:25 +01:00
parent a9543347af
commit 0889960232
14 changed files with 156 additions and 75 deletions

14
HISTORY
View File

@ -6276,7 +6276,7 @@ Video Disk Recorder Revision History
- Fixed plugin arguments corruption with glibc 2.11 on x86_64 (thanks to
Anssi Hannula).
2010-01-24: Version 1.7.12
2010-01-30: Version 1.7.12
- Changed the EVCONTENTMASK_* macros to enums and changed "mask" to "group".
- Updated the Estonian OSD texts (thanks to Arthur Konovalov).
@ -6296,9 +6296,13 @@ Video Disk Recorder Revision History
to Matti Lehtimäki).
- Fixed determining the frame duration on channels where the PTS deltas jitter by
+/-1 around 1800.
- The PCR pid in generated PMTs is now set to the channel's PCR pid again, which
in most cases is the same as the video pid. For channels that use a separate
PCR pid, no TS packets are recorded from that PID (I have yet to see a case where
this actually is a problem).
- The PCR pid in generated PMTs is now set to the channel's PCR pid again.
- Fixed determining the frame duration on channels where the PTS deltas jitter by
+/-1 around 3600.
- The PCR pid is now recorded for channels where this is different from the video
PID. To facilitate this, the interfaces of cTransfer, cTransferControl, cRecorder
and cReceiver have been modified, so that the PIDs are no longer given in separate
parameters, but rather the whole channel is handed down for processing. The old
constructor of cReceiver is still available, but it is recommended to plugin authors
that they switch to the new interface as soon as possible.
When replaying such a recording, the PCR packets are sent to PlayTsVideo()

View File

@ -10,3 +10,8 @@ VDR Plugin 'dvbsddevice' Revision History
- Calling the MakePrimaryDevice() function of the base class to allow
the cDevice to stop displaying subtitles.
- Added support for DVB cards with multiple fontends.
2010-01-30: Version 0.0.3
- The PCR pid is now recorded for channels where this is different from the
video PID.

View File

@ -3,13 +3,13 @@
*
* See the README file for copyright information and how to reach the author.
*
* $Id: dvbsddevice.c 1.2 2010/01/01 15:01:01 kls Exp $
* $Id: dvbsddevice.c 1.3 2010/01/30 10:05:42 kls Exp $
*/
#include <vdr/plugin.h>
#include "dvbsdffdevice.h"
static const char *VERSION = "0.0.2";
static const char *VERSION = "0.0.3";
static const char *DESCRIPTION = "SD Full Featured DVB device";
class cPluginDvbsddevice : public cPlugin {

View File

@ -3,7 +3,7 @@
*
* See the README file for copyright information and how to reach the author.
*
* $Id: dvbsdffdevice.c 2.25 2010/01/04 12:56:56 kls Exp $
* $Id: dvbsdffdevice.c 2.26 2010/01/30 10:05:23 kls Exp $
*/
#include "dvbsdffdevice.h"
@ -434,7 +434,7 @@ bool cDvbSdFfDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, true));
}
else if (StartTransferMode)
cControl::Launch(new cTransferControl(this, Channel->GetChannelID(), vpid, Channel->Apids(), Channel->Dpids(), Channel->Spids()));
cControl::Launch(new cTransferControl(this, Channel));
return true;
}

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: device.c 2.31 2010/01/01 15:40:35 kls Exp $
* $Id: device.c 2.32 2010/01/30 11:06:51 kls Exp $
*/
#include "device.h"
@ -30,8 +30,8 @@ public:
};
cLiveSubtitle::cLiveSubtitle(int SPid)
:cReceiver(tChannelID(), -1, SPid)
{
AddPid(SPid);
}
cLiveSubtitle::~cLiveSubtitle()
@ -676,7 +676,7 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
if (Device && CanReplay()) {
cStatus::MsgChannelSwitch(this, 0); // only report status if we are actually going to switch the channel
if (Device->SetChannel(Channel, false) == scrOk) // calling SetChannel() directly, not SwitchChannel()!
cControl::Launch(new cTransferControl(Device, Channel->GetChannelID(), Channel->Vpid(), Channel->Apids(), Channel->Dpids(), Channel->Spids()));
cControl::Launch(new cTransferControl(Device, Channel));
else
Result = scrNoTransfer;
}
@ -1364,10 +1364,10 @@ int cDevice::PlayTs(const uchar *Data, int Length, bool VideoOnly)
esyslog("ERROR: skipped %d bytes to sync on start of TS packet", Skipped);
return Played + Skipped;
}
int Pid = TsPid(Data);
if (TsHasPayload(Data)) { // silently ignore TS packets w/o payload
int PayloadOffset = TsPayloadOffset(Data);
if (PayloadOffset < TS_SIZE) {
int Pid = TsPid(Data);
if (Pid == 0)
patPmtParser.ParsePat(Data, TS_SIZE);
else if (Pid == patPmtParser.PmtPid())
@ -1396,6 +1396,13 @@ int cDevice::PlayTs(const uchar *Data, int Length, bool VideoOnly)
}
}
}
else if (Pid == patPmtParser.Ppid()) {
int w = PlayTsVideo(Data, TS_SIZE);
if (w < 0)
return Played ? Played : w;
if (w == 0)
break;
}
Played += TS_SIZE;
Length -= TS_SIZE;
Data += TS_SIZE;

4
menu.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: menu.c 2.12 2010/01/17 15:10:07 kls Exp $
* $Id: menu.c 2.13 2010/01/29 16:36:57 kls Exp $
*/
#include "menu.h"
@ -4055,7 +4055,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->GetChannelID(), timer->Priority(), ch->Vpid(), ch->Apids(), ch->Dpids(), ch->Spids());
recorder = new cRecorder(fileName, ch, timer->Priority());
if (device->AttachReceiver(recorder)) {
Recording.WriteInfo();
cStatus::MsgRecording(device, Recording.Name(), Recording.FileName(), true);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: receiver.c 2.1 2010/01/01 15:38:48 kls Exp $
* $Id: receiver.c 2.2 2010/01/30 10:25:38 kls Exp $
*/
#include "receiver.h"
@ -12,28 +12,26 @@
#include <stdio.h>
#include "tools.h"
#ifdef LEGACY_CRECEIVER
cReceiver::cReceiver(tChannelID ChannelID, int Priority, int Pid, const int *Pids1, const int *Pids2, const int *Pids3)
{
device = NULL;
channelID = ChannelID;
priority = Priority;
numPids = 0;
if (Pid)
pids[numPids++] = Pid;
if (Pids1) {
while (*Pids1 && numPids < MAXRECEIVEPIDS)
pids[numPids++] = *Pids1++;
}
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");
AddPid(Pid);
AddPids(Pids1);
AddPids(Pids2);
AddPids(Pids3);
}
#endif
cReceiver::cReceiver(const cChannel *Channel, int Priority)
{
device = NULL;
priority = Priority;
numPids = 0;
SetPids(Channel);
}
cReceiver::~cReceiver()
@ -46,6 +44,49 @@ cReceiver::~cReceiver()
}
}
bool cReceiver::AddPid(int Pid)
{
if (Pid) {
if (numPids < MAXRECEIVEPIDS)
pids[numPids++] = Pid;
else {
dsyslog("too many PIDs in cReceiver (Pid = %d)", Pid);
return false;
}
}
return true;
}
bool cReceiver::AddPids(const int *Pids)
{
if (Pids) {
while (*Pids) {
if (!AddPid(*Pids++))
return false;
}
}
return true;
}
bool cReceiver::AddPids(int Pid1, int Pid2, int Pid3, int Pid4, int Pid5, int Pid6, int Pid7, int Pid8, int Pid9)
{
return AddPid(Pid1) && AddPid(Pid2) && AddPid(Pid3) && AddPid(Pid4) && AddPid(Pid5) && AddPid(Pid6) && AddPid(Pid7) && AddPid(Pid8) && AddPid(Pid9);
}
bool cReceiver::SetPids(const cChannel *Channel)
{
numPids = 0;
if (Channel) {
channelID = Channel->GetChannelID();
return AddPid(Channel->Vpid()) &&
(Channel->Ppid() == Channel->Vpid() || AddPid(Channel->Ppid())) &&
AddPids(Channel->Apids()) &&
(!Setup.UseDolbyDigital || AddPids(Channel->Dpids())) &&
AddPids(Channel->Spids());
}
return true;
}
bool cReceiver::WantsPid(int Pid)
{
if (Pid) {

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: receiver.h 1.5 2007/01/07 14:40:36 kls Exp $
* $Id: receiver.h 2.1 2010/01/30 10:25:19 kls Exp $
*/
#ifndef __RECEIVER_H
@ -14,6 +14,8 @@
#define MAXRECEIVEPIDS 64 // the maximum number of PIDs per receiver
#define LEGACY_CRECEIVER // Code enclosed with this macro is deprecated and may be removed in a future version
class cReceiver {
friend class cDevice;
private:
@ -38,20 +40,35 @@ protected:
///< will be delivered only ONCE, so the cReceiver must make sure that
///< it will be able to buffer the data if necessary.
public:
#ifdef LEGACY_CRECEIVER
cReceiver(tChannelID ChannelID, int Priority, int Pid, const int *Pids1 = NULL, const int *Pids2 = NULL, const int *Pids3 = NULL);
///< Creates a new receiver for the channel with the given ChannelID with
///< 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.
#endif
cReceiver(const cChannel *Channel = NULL, int Priority = -1);
///< Creates a new receiver for the given Channel with the given Priority.
///< If Channel is not NULL, its pids set by a call to SetPids().
///< Otherwise pids can be added to the receiver by separate calls to the AddPid[s]
///< functions.
///< The total number of PIDs added to a receiver must not exceed MAXRECEIVEPIDS.
///< Priority may be any value in the range -99..99. Negative values indicate
///< that this cReceiver may be detached at any time (without blocking the
///< cDevice it is attached to).
///< The ChannelID is necessary to allow the device that will be used for this
///< receiver to detect and store whether the channel can be decrypted in case
///< this is an encrypted channel. If the channel is not encrypted or this
///< detection is not wanted, an invalid tChannelID may be given.
virtual ~cReceiver();
bool AddPid(int Pid);
///< Adds the given Pid to the list of PIDs of this receiver.
bool AddPids(const int *Pids);
///< Adds the given izero terminated list of Pids to the list of PIDs of this
///< receiver.
bool AddPids(int Pid1, int Pid2, int Pid3 = 0, int Pid4 = 0, int Pid5 = 0, int Pid6 = 0, int Pid7 = 0, int Pid8 = 0, int Pid9 = 0);
///< Adds the given Pids to the list of PIDs of this receiver.
bool SetPids(const cChannel *Channel);
///< Sets the PIDs of this receiver to those of the given Channel,
///< replacing and previously stored PIDs. If Channel is NULL, all
///< PIDs will be cleared. Parameters in the Setup may control whether
///< certain types of PIDs (like Dolby Digital, for instance) are
///< actually set. The Channel's ID is stored and can later be retrieved
///< through ChannelID(). The ChannelID is necessary to allow the device
///< that will be used for this receiver to detect and store whether the
///< channel can be decrypted in case this is an encrypted channel.
tChannelID ChannelID(void) { return channelID; }
bool IsAttached(void) { return device != NULL; }
///< Returns true if this receiver is (still) attached to a device.

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: recorder.c 2.7 2009/12/06 11:34:41 kls Exp $
* $Id: recorder.c 2.8 2010/01/29 16:37:22 kls Exp $
*/
#include "recorder.h"
@ -21,8 +21,8 @@
// --- cRecorder -------------------------------------------------------------
cRecorder::cRecorder(const char *FileName, tChannelID ChannelID, int Priority, int VPid, const int *APids, const int *DPids, const int *SPids)
:cReceiver(ChannelID, Priority, VPid, APids, Setup.UseDolbyDigital ? DPids : NULL, SPids)
cRecorder::cRecorder(const char *FileName, const cChannel *Channel, int Priority)
:cReceiver(Channel, Priority)
,cThread("recording")
,recordingInfo(FileName)
{
@ -32,15 +32,15 @@ cRecorder::cRecorder(const char *FileName, tChannelID ChannelID, int Priority, i
ringBuffer = new cRingBufferLinear(RECORDERBUFSIZE, MIN_TS_PACKETS_FOR_FRAME_DETECTOR * TS_SIZE, true, "Recorder");
ringBuffer->SetTimeouts(0, 100);
cChannel *Channel = Channels.GetByChannelID(ChannelID);
int Pid = VPid;
int Type = Channel ? Channel->Vtype() : 0;
if (!Pid && APids) {
Pid = APids[0];
int Pid = Channel->Vpid();
int Type = Channel->Vtype();
if (!Pid && Channel->Apid(0)) {
Pid = Channel->Apid(0);
Type = 0x04;
}
if (!Pid && DPids) {
Pid = DPids[0];
if (!Pid && Channel->Dpid(0)) {
Pid = Channel->Dpid(0);
Type = 0x06;
}
frameDetector = new cFrameDetector(Pid, Type);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: recorder.h 2.1 2009/01/06 10:44:58 kls Exp $
* $Id: recorder.h 2.2 2010/01/29 16:32:32 kls Exp $
*/
#ifndef __RECORDER_H
@ -34,9 +34,9 @@ protected:
virtual void Receive(uchar *Data, int Length);
virtual void Action(void);
public:
cRecorder(const char *FileName, tChannelID ChannelID, int Priority, int VPid, const int *APids, const int *DPids, const int *SPids);
// Creates a new recorder for the channel with the given ChannelID and
// the given Priority that will record the given PIDs into the file FileName.
cRecorder(const char *FileName, const cChannel *Channel, int Priority);
// Creates a new recorder for the given Channel and
// the given Priority that will record into the file FileName.
virtual ~cRecorder();
};

13
remux.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: remux.c 2.40 2010/01/24 16:13:12 kls Exp $
* $Id: remux.c 2.41 2010/01/30 10:43:12 kls Exp $
*/
#include "remux.h"
@ -144,7 +144,7 @@ void TsSetTeiOnBrokenPackets(uchar *p, int l)
// --- cPatPmtGenerator ------------------------------------------------------
cPatPmtGenerator::cPatPmtGenerator(cChannel *Channel)
cPatPmtGenerator::cPatPmtGenerator(const cChannel *Channel)
{
numPmtPackets = 0;
patCounter = pmtCounter = 0;
@ -243,7 +243,7 @@ int cPatPmtGenerator::MakeCRC(uchar *Target, const uchar *Data, int Length)
#define P_PMT_PID 0x0084 // pseudo PMT pid
#define MAXPID 0x2000 // the maximum possible number of pids
void cPatPmtGenerator::GeneratePmtPid(cChannel *Channel)
void cPatPmtGenerator::GeneratePmtPid(const cChannel *Channel)
{
bool Used[MAXPID] = { false };
#define SETPID(p) { if ((p) >= 0 && (p) < MAXPID) Used[p] = true; }
@ -287,7 +287,7 @@ void cPatPmtGenerator::GeneratePat(void)
IncVersion(patVersion);
}
void cPatPmtGenerator::GeneratePmt(cChannel *Channel)
void cPatPmtGenerator::GeneratePmt(const cChannel *Channel)
{
// generate the complete PMT section:
uchar buf[MAX_SECTION_SIZE];
@ -364,7 +364,7 @@ void cPatPmtGenerator::SetVersions(int PatVersion, int PmtVersion)
pmtVersion = PmtVersion & 0x1F;
}
void cPatPmtGenerator::SetChannel(cChannel *Channel)
void cPatPmtGenerator::SetChannel(const cChannel *Channel)
{
if (Channel) {
GeneratePmtPid(Channel);
@ -402,6 +402,7 @@ void cPatPmtParser::Reset(void)
patVersion = pmtVersion = -1;
pmtPid = -1;
vpid = vtype = 0;
ppid = 0;
}
void cPatPmtParser::ParsePat(const uchar *Data, int Length)
@ -486,6 +487,7 @@ void cPatPmtParser::ParsePmt(const uchar *Data, int Length)
int NumDpids = 0;
int NumSpids = 0;
vpid = vtype = 0;
ppid = 0;
apids[0] = 0;
dpids[0] = 0;
spids[0] = 0;
@ -500,6 +502,7 @@ void cPatPmtParser::ParsePmt(const uchar *Data, int Length)
case 0x1B: // MPEG4
vpid = stream.getPid();
vtype = stream.getStreamType();
ppid = Pmt.getPCRPid();
break;
case 0x03: // STREAMTYPE_11172_AUDIO
case 0x04: // STREAMTYPE_13818_AUDIO

14
remux.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: remux.h 2.23 2009/12/31 15:35:37 kls Exp $
* $Id: remux.h 2.24 2010/01/29 16:51:26 kls Exp $
*/
#ifndef __REMUX_H
@ -172,16 +172,16 @@ protected:
int MakeSubtitlingDescriptor(uchar *Target, const char *Language, uchar SubtitlingType, uint16_t CompositionPageId, uint16_t AncillaryPageId);
int MakeLanguageDescriptor(uchar *Target, const char *Language);
int MakeCRC(uchar *Target, const uchar *Data, int Length);
void GeneratePmtPid(cChannel *Channel);
void GeneratePmtPid(const cChannel *Channel);
///< Generates a PMT pid that doesn't collide with any of the actual
///< pids of the Channel.
void GeneratePat(void);
///< Generates a PAT section for later use with GetPat().
void GeneratePmt(cChannel *Channel);
void GeneratePmt(const cChannel *Channel);
///< Generates a PMT section for the given Channel, for later use
///< with GetPmt().
public:
cPatPmtGenerator(cChannel *Channel = NULL);
cPatPmtGenerator(const cChannel *Channel = NULL);
void SetVersions(int PatVersion, int PmtVersion);
///< Sets the version numbers for the generated PAT and PMT, in case
///< this generator is used to, e.g., continue a previously interrupted
@ -191,7 +191,7 @@ public:
///< higher bits will automatically be cleared.
///< SetVersions() needs to be called before SetChannel() in order to
///< have an effect from the very start.
void SetChannel(cChannel *Channel);
void SetChannel(const cChannel *Channel);
///< Sets the Channel for which the PAT/PMT shall be generated.
uchar *GetPat(void);
///< Returns a pointer to the PAT section, which consists of exactly
@ -213,6 +213,7 @@ private:
int pmtVersion;
int pmtPid;
int vpid;
int ppid;
int vtype;
int apids[MAXAPIDS + 1]; // list is zero-terminated
int atypes[MAXAPIDS + 1]; // list is zero-terminated
@ -252,6 +253,9 @@ public:
int Vpid(void) const { return vpid; }
///< Returns the video pid as defined by the current PMT, or 0 if no video
///< pid has been detected, yet.
int Ppid(void) const { return ppid; }
///< Returns the PCR pid as defined by the current PMT, or 0 if no PCR
///< pid has been detected, yet.
int Vtype(void) const { return vtype; }
///< Returns the video stream type as defined by the current PMT, or 0 if no video
///< stream type has been detected, yet.

View File

@ -4,17 +4,17 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: transfer.c 2.4 2009/12/06 14:22:23 kls Exp $
* $Id: transfer.c 2.5 2010/01/30 11:10:25 kls Exp $
*/
#include "transfer.h"
// --- cTransfer -------------------------------------------------------------
cTransfer::cTransfer(tChannelID ChannelID, int VPid, const int *APids, const int *DPids, const int *SPids)
:cReceiver(ChannelID, -1, VPid, APids, Setup.UseDolbyDigital ? DPids : NULL, SPids)
cTransfer::cTransfer(const cChannel *Channel)
:cReceiver(Channel)
{
patPmtGenerator.SetChannel(Channels.GetByChannelID(ChannelID));
patPmtGenerator.SetChannel(Channel);
}
cTransfer::~cTransfer()
@ -55,8 +55,8 @@ void cTransfer::Receive(uchar *Data, int Length)
cDevice *cTransferControl::receiverDevice = NULL;
cTransferControl::cTransferControl(cDevice *ReceiverDevice, tChannelID ChannelID, int VPid, const int *APids, const int *DPids, const int *SPids)
:cControl(transfer = new cTransfer(ChannelID, VPid, APids, DPids, SPids), true)
cTransferControl::cTransferControl(cDevice *ReceiverDevice, const cChannel *Channel)
:cControl(transfer = new cTransfer(Channel), true)
{
ReceiverDevice->AttachReceiver(transfer);
receiverDevice = ReceiverDevice;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: transfer.h 2.1 2008/05/25 12:44:49 kls Exp $
* $Id: transfer.h 2.2 2010/01/29 16:38:09 kls Exp $
*/
#ifndef __TRANSFER_H
@ -21,7 +21,7 @@ protected:
virtual void Activate(bool On);
virtual void Receive(uchar *Data, int Length);
public:
cTransfer(tChannelID ChannelID, int VPid, const int *APids, const int *DPids, const int *SPids);
cTransfer(const cChannel *Channel);
virtual ~cTransfer();
};
@ -30,7 +30,7 @@ private:
cTransfer *transfer;
static cDevice *receiverDevice;
public:
cTransferControl(cDevice *ReceiverDevice, tChannelID ChannelID, int VPid, const int *APids, const int *DPids, const int *SPids);
cTransferControl(cDevice *ReceiverDevice, const cChannel *Channel);
~cTransferControl();
virtual void Hide(void) {}
static cDevice *ReceiverDevice(void) { return receiverDevice; }