mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
No longer permanently looping through PMT PIDs, which caused problems with some SatIP receivers
This commit is contained in:
parent
58e21d8e37
commit
7b1c097958
@ -2343,6 +2343,7 @@ Andr
|
|||||||
for reporting a bug in selecting the last replayed recording in the Recordings menu
|
for reporting a bug in selecting the last replayed recording in the Recordings menu
|
||||||
in case there are folders and plain recordings with names that differ only in
|
in case there are folders and plain recordings with names that differ only in
|
||||||
non-alphanumeric characters
|
non-alphanumeric characters
|
||||||
|
for reporting a problem with permanently looping through PMT PIDs on a SatIP receiver
|
||||||
|
|
||||||
Jürgen Schilling <juergen_schilling@web.de>
|
Jürgen Schilling <juergen_schilling@web.de>
|
||||||
for reporting that color buttons were displayed in the recording info menu if it
|
for reporting that color buttons were displayed in the recording info menu if it
|
||||||
|
4
HISTORY
4
HISTORY
@ -9706,7 +9706,7 @@ Video Disk Recorder Revision History
|
|||||||
order to restore this functionality. However, it is recommended to use the function
|
order to restore this functionality. However, it is recommended to use the function
|
||||||
with the TimerActive parameter instead.
|
with the TimerActive parameter instead.
|
||||||
|
|
||||||
2021-05-26:
|
2021-06-08:
|
||||||
|
|
||||||
- cRecordingInfo::Errors() now returns -1 for old recordings; added a missing 'const'
|
- cRecordingInfo::Errors() now returns -1 for old recordings; added a missing 'const'
|
||||||
(suggested by Christoph Haubrich).
|
(suggested by Christoph Haubrich).
|
||||||
@ -9714,3 +9714,5 @@ Video Disk Recorder Revision History
|
|||||||
- Added missing initialization of cRecorder::lastErrors.
|
- Added missing initialization of cRecorder::lastErrors.
|
||||||
- Now using __cplusplus instead of DISABLE_TEMPLATES_COLLIDING_WITH_STL, and using
|
- Now using __cplusplus instead of DISABLE_TEMPLATES_COLLIDING_WITH_STL, and using
|
||||||
std::min(), std::max() and std::swap() if available (thanks to Winfried Köhler).
|
std::min(), std::max() and std::swap() if available (thanks to Winfried Köhler).
|
||||||
|
- No longer permanently looping through PMT PIDs, which caused problems with some
|
||||||
|
SatIP receivers (reported by André Weidemann; with help from Helmut Binder).
|
||||||
|
17
device.c
17
device.c
@ -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 5.2 2021/03/17 10:59:36 kls Exp $
|
* $Id: device.c 5.3 2021/06/08 14:57:26 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
@ -858,6 +858,13 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
|
|||||||
cStatus::MsgChannelSwitch(this, 0, LiveView);
|
cStatus::MsgChannelSwitch(this, 0, LiveView);
|
||||||
|
|
||||||
if (LiveView) {
|
if (LiveView) {
|
||||||
|
if (IsPrimaryDevice() && !Replaying() && !Transferring()) { // this is only for FF DVB cards!
|
||||||
|
LOCK_CHANNELS_READ;
|
||||||
|
if (const cChannel *ch = Channels->GetByNumber(currentChannel)) {
|
||||||
|
if (patFilter)
|
||||||
|
patFilter->Release(ch->Sid());
|
||||||
|
}
|
||||||
|
}
|
||||||
StopReplay();
|
StopReplay();
|
||||||
DELETENULL(liveSubtitle);
|
DELETENULL(liveSubtitle);
|
||||||
DELETENULL(dvbSubtitleConverter);
|
DELETENULL(dvbSubtitleConverter);
|
||||||
@ -898,8 +905,6 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
|
|||||||
if (SetChannelDevice(Channel, LiveView)) {
|
if (SetChannelDevice(Channel, LiveView)) {
|
||||||
// Start section handling:
|
// Start section handling:
|
||||||
if (sectionHandler) {
|
if (sectionHandler) {
|
||||||
if (patFilter)
|
|
||||||
patFilter->Trigger(Channel->Sid());
|
|
||||||
sectionHandler->SetChannel(Channel);
|
sectionHandler->SetChannel(Channel);
|
||||||
sectionHandler->SetStatus(true);
|
sectionHandler->SetStatus(true);
|
||||||
}
|
}
|
||||||
@ -913,6 +918,8 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
|
|||||||
|
|
||||||
if (Result == scrOk) {
|
if (Result == scrOk) {
|
||||||
if (LiveView && IsPrimaryDevice()) {
|
if (LiveView && IsPrimaryDevice()) {
|
||||||
|
if (patFilter) // this is only for FF DVB cards!
|
||||||
|
patFilter->Request(Channel->Sid());
|
||||||
currentChannel = Channel->Number();
|
currentChannel = Channel->Number();
|
||||||
// Set the available audio tracks:
|
// Set the available audio tracks:
|
||||||
ClrAvailableTracks();
|
ClrAvailableTracks();
|
||||||
@ -1807,6 +1814,8 @@ bool cDevice::AttachReceiver(cReceiver *Receiver)
|
|||||||
dsyslog("CAM %d: %sknown to decrypt channel %s (scramblingTimeout = %ds)", camSlot->MasterSlotNumber(), KnownToDecrypt ? "" : "not ", *Receiver->ChannelID().ToString(), Receiver->scramblingTimeout);
|
dsyslog("CAM %d: %sknown to decrypt channel %s (scramblingTimeout = %ds)", camSlot->MasterSlotNumber(), KnownToDecrypt ? "" : "not ", *Receiver->ChannelID().ToString(), Receiver->scramblingTimeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (patFilter && Receiver->ChannelID().Valid())
|
||||||
|
patFilter->Request(Receiver->ChannelID().Sid());
|
||||||
Start();
|
Start();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1827,6 +1836,8 @@ void cDevice::Detach(cReceiver *Receiver)
|
|||||||
else if (receiver[i])
|
else if (receiver[i])
|
||||||
receiversLeft = true;
|
receiversLeft = true;
|
||||||
}
|
}
|
||||||
|
if (patFilter && Receiver->ChannelID().Valid())
|
||||||
|
patFilter->Release(Receiver->ChannelID().Sid());
|
||||||
mutexReceiver.Unlock();
|
mutexReceiver.Unlock();
|
||||||
Receiver->device = NULL;
|
Receiver->device = NULL;
|
||||||
Receiver->Activate(false);
|
Receiver->Activate(false);
|
||||||
|
219
pat.c
219
pat.c
@ -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 5.1 2021/03/16 15:10:54 kls Exp $
|
* $Id: pat.c 5.2 2021/06/08 14:57:26 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pat.h"
|
#include "pat.h"
|
||||||
@ -285,10 +285,20 @@ int GetPmtPid(int Source, int Transponder, int ServiceId)
|
|||||||
class cPmtPidEntry : public cListObject {
|
class cPmtPidEntry : public cListObject {
|
||||||
private:
|
private:
|
||||||
int pid;
|
int pid;
|
||||||
bool complete;
|
int count; // the number of SIDs currently requested from this PID
|
||||||
|
int state; // adding/deleting PIDs to/from the filter may only be done from within the Process() function,
|
||||||
|
// otherwise there could be a deadlock between cPatFilter::mutex and cSectionHandler::mutex;
|
||||||
|
// this member tells whether this PID needs to be added to (>0) or deleted from (<0) the filter
|
||||||
|
bool complete; // true if all SIDs on this PID have been received
|
||||||
public:
|
public:
|
||||||
cPmtPidEntry(int Pid);
|
cPmtPidEntry(int Pid);
|
||||||
int Pid(void) { return pid; }
|
int Pid(void) { return pid; }
|
||||||
|
int Count(void) { return count; }
|
||||||
|
int State(void) { int s = state; state = 0; return s; } // returns the current state and resets it
|
||||||
|
void SetState(void) { state = 1; }
|
||||||
|
void ClrState(void) { state = -1; }
|
||||||
|
void Inc(void) { if (++count == 1) state = 1; }
|
||||||
|
void Dec(void) { if (--count == 0) state = -1; }
|
||||||
int Complete(void) { return complete; }
|
int Complete(void) { return complete; }
|
||||||
void SetComplete(bool State) { complete = State; }
|
void SetComplete(bool State) { complete = State; }
|
||||||
};
|
};
|
||||||
@ -296,6 +306,8 @@ public:
|
|||||||
cPmtPidEntry::cPmtPidEntry(int Pid)
|
cPmtPidEntry::cPmtPidEntry(int Pid)
|
||||||
{
|
{
|
||||||
pid = Pid;
|
pid = Pid;
|
||||||
|
count = 0;
|
||||||
|
state = 0;
|
||||||
complete = false;
|
complete = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,7 +321,7 @@ private:
|
|||||||
int version;
|
int version;
|
||||||
bool received;
|
bool received;
|
||||||
public:
|
public:
|
||||||
cPmtSidEntry(int Sid, int Pid, cPmtPidEntry *PidEntry);
|
cPmtSidEntry(int Sid, cPmtPidEntry *PidEntry);
|
||||||
int Sid(void) { return sid; }
|
int Sid(void) { return sid; }
|
||||||
int Pid(void) { return pid; }
|
int Pid(void) { return pid; }
|
||||||
cPmtPidEntry *PidEntry(void) { return pidEntry; }
|
cPmtPidEntry *PidEntry(void) { return pidEntry; }
|
||||||
@ -319,15 +331,29 @@ public:
|
|||||||
void SetReceived(bool State) { received = State; }
|
void SetReceived(bool State) { received = State; }
|
||||||
};
|
};
|
||||||
|
|
||||||
cPmtSidEntry::cPmtSidEntry(int Sid, int Pid, cPmtPidEntry *PidEntry)
|
cPmtSidEntry::cPmtSidEntry(int Sid, cPmtPidEntry *PidEntry)
|
||||||
{
|
{
|
||||||
sid = Sid;
|
sid = Sid;
|
||||||
pid = Pid;
|
pid = PidEntry->Pid();
|
||||||
pidEntry = PidEntry;
|
pidEntry = PidEntry;
|
||||||
version = -1;
|
version = -1;
|
||||||
received = false;
|
received = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- cPmtSidRequest --------------------------------------------------------
|
||||||
|
|
||||||
|
class cPmtSidRequest : public cListObject {
|
||||||
|
private:
|
||||||
|
int sid;
|
||||||
|
int count; // the number of requests for this SID
|
||||||
|
public:
|
||||||
|
cPmtSidRequest(int Sid) { sid = Sid; count = 1; }
|
||||||
|
int Sid(void) { return sid; }
|
||||||
|
int Count(void) { return count; }
|
||||||
|
void Inc(void) { count++; }
|
||||||
|
void Dec(void) { count--; }
|
||||||
|
};
|
||||||
|
|
||||||
// --- cPatFilter ------------------------------------------------------------
|
// --- cPatFilter ------------------------------------------------------------
|
||||||
|
|
||||||
//#define DEBUG_PAT_PMT
|
//#define DEBUG_PAT_PMT
|
||||||
@ -339,32 +365,95 @@ cPmtSidEntry::cPmtSidEntry(int Sid, int Pid, cPmtPidEntry *PidEntry)
|
|||||||
|
|
||||||
cPatFilter::cPatFilter(void)
|
cPatFilter::cPatFilter(void)
|
||||||
{
|
{
|
||||||
Trigger(0);
|
patVersion = -1;
|
||||||
|
activePmt = NULL;
|
||||||
|
transponder = 0;
|
||||||
|
source = 0;
|
||||||
Set(0x00, 0x00); // PAT
|
Set(0x00, 0x00); // PAT
|
||||||
}
|
}
|
||||||
|
|
||||||
void cPatFilter::SetStatus(bool On)
|
bool cPatFilter::TransponderChanged(void)
|
||||||
{
|
{
|
||||||
cMutexLock MutexLock(&mutex);
|
if (source != Source() || transponder != Transponder()) {
|
||||||
DBGLOG("PAT filter set status %d", On);
|
DBGLOG("PAT filter transponder changed from %d/%d to %d/%d", source, transponder, Source(), Transponder());
|
||||||
cFilter::SetStatus(On);
|
source = Source();
|
||||||
Trigger();
|
transponder = Transponder();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cPatFilter::Trigger(int Sid)
|
void cPatFilter::Trigger(int)
|
||||||
{
|
{
|
||||||
cMutexLock MutexLock(&mutex);
|
cMutexLock MutexLock(&mutex);
|
||||||
patVersion = -1;
|
DBGLOG("PAT filter trigger");
|
||||||
sectionSyncer.Reset();
|
if (activePmt != pmtPidList.First()) {
|
||||||
if (Sid != 0 && activePmt)
|
if (activePmt && activePmt->Count() == 0)
|
||||||
Del(activePmt->Pid(), SI::TableIdPMT);
|
activePmt->ClrState();
|
||||||
activePmt = NULL;
|
activePmt = pmtPidList.First();
|
||||||
if (Sid >= 0) {
|
if (activePmt && activePmt->Count() == 0) {
|
||||||
sid = Sid;
|
activePmt->SetState();
|
||||||
DBGLOG("PAT filter trigger SID %d", Sid);
|
timer.Set(PMT_SCAN_TIMEOUT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cPatFilter::Request(int Sid)
|
||||||
|
{
|
||||||
|
cMutexLock MutexLock(&mutex);
|
||||||
|
DBGLOG("PAT filter request SID %d", Sid);
|
||||||
|
for (cPmtSidRequest *sr = pmtSidRequestList.First(); sr; sr = pmtSidRequestList.Next(sr)) {
|
||||||
|
if (sr->Sid() == Sid) {
|
||||||
|
sr->Inc();
|
||||||
|
DBGLOG("PAT filter add SID request %d (%d)", Sid, sr->Count());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DBGLOG("PAT filter new SID request %d", Sid);
|
||||||
|
pmtSidRequestList.Add(new cPmtSidRequest(Sid));
|
||||||
|
for (cPmtSidEntry *se = pmtSidList.First(); se; se = pmtSidList.Next(se)) {
|
||||||
|
if (se->Sid() == Sid) {
|
||||||
|
cPmtPidEntry *pPid = se->PidEntry();
|
||||||
|
pPid->Inc();
|
||||||
|
DBGLOG(" PMT pid %5d SID %5d (%d)", pPid->Pid(), se->Sid(), pPid->Count());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cPatFilter::Release(int Sid)
|
||||||
|
{
|
||||||
|
cMutexLock MutexLock(&mutex);
|
||||||
|
DBGLOG("PAT filter release SID %d", Sid);
|
||||||
|
for (cPmtSidRequest *sr = pmtSidRequestList.First(); sr; sr = pmtSidRequestList.Next(sr)) {
|
||||||
|
if (sr->Sid() == Sid) {
|
||||||
|
sr->Dec();
|
||||||
|
DBGLOG("PAT filter del SID request %d (%d)", Sid, sr->Count());
|
||||||
|
if (sr->Count() == 0) {
|
||||||
|
pmtSidRequestList.Del(sr);
|
||||||
|
for (cPmtSidEntry *se = pmtSidList.First(); se; se = pmtSidList.Next(se)) {
|
||||||
|
if (se->Sid() == Sid) {
|
||||||
|
cPmtPidEntry *pPid = se->PidEntry();
|
||||||
|
pPid->Dec();
|
||||||
|
DBGLOG(" PMT pid %5d SID %5d (%d)", pPid->Pid(), se->Sid(), pPid->Count());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int cPatFilter::NumSidRequests(int Sid)
|
||||||
|
{
|
||||||
|
for (cPmtSidRequest *sr = pmtSidRequestList.First(); sr; sr = pmtSidRequestList.Next(sr)) {
|
||||||
|
if (sr->Sid() == Sid)
|
||||||
|
return sr->Count();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool cPatFilter::PmtPidComplete(int PmtPid)
|
bool cPatFilter::PmtPidComplete(int PmtPid)
|
||||||
{
|
{
|
||||||
for (cPmtSidEntry *se = pmtSidList.First(); se; se = pmtSidList.Next(se)) {
|
for (cPmtSidEntry *se = pmtSidList.First(); se; se = pmtSidList.Next(se)) {
|
||||||
@ -377,15 +466,16 @@ bool cPatFilter::PmtPidComplete(int PmtPid)
|
|||||||
void cPatFilter::PmtPidReset(int PmtPid)
|
void cPatFilter::PmtPidReset(int PmtPid)
|
||||||
{
|
{
|
||||||
for (cPmtSidEntry *se = pmtSidList.First(); se; se = pmtSidList.Next(se)) {
|
for (cPmtSidEntry *se = pmtSidList.First(); se; se = pmtSidList.Next(se)) {
|
||||||
if (se->Pid() == PmtPid)
|
if (se->Pid() == PmtPid) {
|
||||||
se->SetReceived(false);
|
se->SetReceived(false);
|
||||||
|
se->PidEntry()->SetComplete(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cPatFilter::PmtVersionChanged(int PmtPid, int Sid, int Version, bool SetNewVersion)
|
bool cPatFilter::PmtVersionChanged(int PmtPid, int Sid, int Version, bool SetNewVersion)
|
||||||
{
|
{
|
||||||
int i = 0;
|
for (cPmtSidEntry *se = pmtSidList.First(); se; se = pmtSidList.Next(se)) {
|
||||||
for (cPmtSidEntry *se = pmtSidList.First(); se; se = pmtSidList.Next(se), i++) {
|
|
||||||
if (se->Sid() == Sid && se->Pid() == PmtPid) {
|
if (se->Sid() == Sid && se->Pid() == PmtPid) {
|
||||||
if (!se->Received()) {
|
if (!se->Received()) {
|
||||||
se->SetReceived(true);
|
se->SetReceived(true);
|
||||||
@ -395,7 +485,7 @@ bool cPatFilter::PmtVersionChanged(int PmtPid, int Sid, int Version, bool SetNew
|
|||||||
if (SetNewVersion)
|
if (SetNewVersion)
|
||||||
se->SetVersion(Version);
|
se->SetVersion(Version);
|
||||||
else
|
else
|
||||||
DBGLOG("PMT %d %2d %5d/%d %2d -> %2d", Transponder(), i, PmtPid, Sid, se->Version(), Version);
|
DBGLOG("PMT %d %5d/%5d %2d -> %2d %d", Transponder(), PmtPid, Sid, se->Version(), Version, NumSidRequests(Sid));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -407,18 +497,39 @@ bool cPatFilter::PmtVersionChanged(int PmtPid, int Sid, int Version, bool SetNew
|
|||||||
void cPatFilter::SwitchToNextPmtPid(void)
|
void cPatFilter::SwitchToNextPmtPid(void)
|
||||||
{
|
{
|
||||||
if (activePmt) {
|
if (activePmt) {
|
||||||
Del(activePmt->Pid(), SI::TableIdPMT);
|
if (activePmt->Count() == 0)
|
||||||
if (!(activePmt = pmtPidList.Next(activePmt)))
|
Del(activePmt->Pid(), SI::TableIdPMT);
|
||||||
activePmt = pmtPidList.First();
|
for (;;) {
|
||||||
PmtPidReset(activePmt->Pid());
|
activePmt = pmtPidList.Next(activePmt);
|
||||||
activePmt->SetComplete(false);
|
if (!activePmt || activePmt->Count() == 0)
|
||||||
Add(activePmt->Pid(), SI::TableIdPMT);
|
break;
|
||||||
|
}
|
||||||
|
if (activePmt) {
|
||||||
|
PmtPidReset(activePmt->Pid());
|
||||||
|
Add(activePmt->Pid(), SI::TableIdPMT);
|
||||||
|
timer.Set(PMT_SCAN_TIMEOUT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length)
|
void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length)
|
||||||
{
|
{
|
||||||
cMutexLock MutexLock(&mutex);
|
cMutexLock MutexLock(&mutex);
|
||||||
|
if (TransponderChanged()) {
|
||||||
|
patVersion = -1;
|
||||||
|
sectionSyncer.Reset();
|
||||||
|
}
|
||||||
|
if (patVersion >= 0) {
|
||||||
|
for (cPmtPidEntry *pPid = pmtPidList.First(); pPid; pPid = pmtPidList.Next(pPid)) {
|
||||||
|
int State = pPid->State();
|
||||||
|
if (State > 0)
|
||||||
|
Add(pPid->Pid(), SI::TableIdPMT);
|
||||||
|
else if (State < 0)
|
||||||
|
Del(pPid->Pid(), SI::TableIdPMT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (Pid != 0x00)
|
||||||
|
return;
|
||||||
if (Pid == 0x00) {
|
if (Pid == 0x00) {
|
||||||
if (Tid == SI::TableIdPAT) {
|
if (Tid == SI::TableIdPAT) {
|
||||||
SI::PAT pat(Data, false);
|
SI::PAT pat(Data, false);
|
||||||
@ -426,13 +537,11 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
|
|||||||
return;
|
return;
|
||||||
if (sectionSyncer.Check(pat.getVersionNumber(), pat.getSectionNumber())) {
|
if (sectionSyncer.Check(pat.getVersionNumber(), pat.getSectionNumber())) {
|
||||||
DBGLOG("PAT %d %d -> %d %d/%d", Transponder(), patVersion, pat.getVersionNumber(), pat.getSectionNumber(), pat.getLastSectionNumber());
|
DBGLOG("PAT %d %d -> %d %d/%d", Transponder(), patVersion, pat.getVersionNumber(), pat.getSectionNumber(), pat.getLastSectionNumber());
|
||||||
|
bool NeedsSetStatus = patVersion >= 0;
|
||||||
if (pat.getVersionNumber() != patVersion) {
|
if (pat.getVersionNumber() != patVersion) {
|
||||||
if (pat.getLastSectionNumber() > 0)
|
if (NeedsSetStatus)
|
||||||
DBGLOG(" PAT %d: %d sections", Transponder(), pat.getLastSectionNumber() + 1);
|
SetStatus(false); // deletes all PIDs from the filter
|
||||||
if (activePmt) {
|
activePmt = NULL;
|
||||||
Del(activePmt->Pid(), SI::TableIdPMT);
|
|
||||||
activePmt = NULL;
|
|
||||||
}
|
|
||||||
pmtSidList.Clear();
|
pmtSidList.Clear();
|
||||||
pmtPidList.Clear();
|
pmtPidList.Clear();
|
||||||
patVersion = pat.getVersionNumber();
|
patVersion = pat.getVersionNumber();
|
||||||
@ -441,36 +550,39 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
|
|||||||
for (SI::Loop::Iterator it; pat.associationLoop.getNext(assoc, it); ) {
|
for (SI::Loop::Iterator it; pat.associationLoop.getNext(assoc, it); ) {
|
||||||
if (!assoc.isNITPid()) {
|
if (!assoc.isNITPid()) {
|
||||||
int PmtPid = assoc.getPid();
|
int PmtPid = assoc.getPid();
|
||||||
|
int PmtSid = assoc.getServiceId();
|
||||||
cPmtPidEntry *pPid = NULL;
|
cPmtPidEntry *pPid = NULL;
|
||||||
int PidIndex = 0;
|
for (pPid = pmtPidList.First(); pPid; pPid = pmtPidList.Next(pPid)) {
|
||||||
for (pPid = pmtPidList.First(); pPid && pPid->Pid() != PmtPid; pPid = pmtPidList.Next(pPid))
|
if (pPid->Pid() == PmtPid)
|
||||||
PidIndex++;
|
break;
|
||||||
|
}
|
||||||
|
int SidRequest = NumSidRequests(PmtSid);
|
||||||
|
DBGLOG(" PMT pid %5d SID %5d%s%s", PmtPid, PmtSid, SidRequest ? " R" : "", pPid ? " S" : "");
|
||||||
if (!pPid) { // new PMT Pid
|
if (!pPid) { // new PMT Pid
|
||||||
pPid = new cPmtPidEntry(PmtPid);
|
pPid = new cPmtPidEntry(PmtPid);
|
||||||
pmtPidList.Add(pPid);
|
pmtPidList.Add(pPid);
|
||||||
}
|
}
|
||||||
pmtSidList.Add(new cPmtSidEntry(assoc.getServiceId(), PmtPid, pPid));
|
pmtSidList.Add(new cPmtSidEntry(PmtSid, pPid));
|
||||||
DBGLOG(" PMT pid %2d/%2d %5d SID %5d", PidIndex, pmtSidList.Count() - 1, PmtPid, assoc.getServiceId());
|
if (SidRequest > 0)
|
||||||
if (sid == assoc.getServiceId()) {
|
pPid->Inc();
|
||||||
activePmt = pPid;
|
|
||||||
DBGLOG("sid = %d pidIndex = %d", sid, PidIndex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sectionSyncer.Processed(pat.getSectionNumber(), pat.getLastSectionNumber())) { // all PAT sections done
|
if (sectionSyncer.Processed(pat.getSectionNumber(), pat.getLastSectionNumber())) { // all PAT sections done
|
||||||
if (pmtPidList.Count() != pmtSidList.Count())
|
for (cPmtPidEntry *pPid = pmtPidList.First(); pPid; pPid = pmtPidList.Next(pPid)) {
|
||||||
DBGLOG(" PAT %d: shared PMT PIDs", Transponder());
|
if (pPid->Count() == 0) {
|
||||||
if (pmtSidList.Count() && !activePmt)
|
pPid->SetState();
|
||||||
activePmt = pmtPidList.First();
|
activePmt = pPid;
|
||||||
if (activePmt)
|
timer.Set(PMT_SCAN_TIMEOUT);
|
||||||
Add(activePmt->Pid(), SI::TableIdPMT);
|
break;
|
||||||
timer.Set(PMT_SCAN_TIMEOUT);
|
}
|
||||||
|
}
|
||||||
|
if (NeedsSetStatus)
|
||||||
|
SetStatus(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (Tid == SI::TableIdPMT && Source() && Transponder()) {
|
else if (Tid == SI::TableIdPMT && Source() && Transponder()) {
|
||||||
timer.Set(PMT_SCAN_TIMEOUT);
|
|
||||||
SI::PMT pmt(Data, false);
|
SI::PMT pmt(Data, false);
|
||||||
if (!pmt.CheckCRCAndParse())
|
if (!pmt.CheckCRCAndParse())
|
||||||
return;
|
return;
|
||||||
@ -731,6 +843,5 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
|
|||||||
if (activePmt)
|
if (activePmt)
|
||||||
DBGLOG("PMT timeout Pid %d", activePmt->Pid());
|
DBGLOG("PMT timeout Pid %d", activePmt->Pid());
|
||||||
SwitchToNextPmtPid();
|
SwitchToNextPmtPid();
|
||||||
timer.Set(PMT_SCAN_TIMEOUT);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
14
pat.h
14
pat.h
@ -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.h 4.2 2020/06/19 12:19:15 kls Exp $
|
* $Id: pat.h 5.1 2021/06/08 14:57:26 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __PAT_H
|
#ifndef __PAT_H
|
||||||
@ -16,27 +16,33 @@
|
|||||||
|
|
||||||
class cPmtPidEntry;
|
class cPmtPidEntry;
|
||||||
class cPmtSidEntry;
|
class cPmtSidEntry;
|
||||||
|
class cPmtSidRequest;
|
||||||
|
|
||||||
class cPatFilter : public cFilter {
|
class cPatFilter : public cFilter {
|
||||||
private:
|
private:
|
||||||
cMutex mutex;
|
cMutex mutex;
|
||||||
cTimeMs timer;
|
cTimeMs timer;
|
||||||
int patVersion;
|
int patVersion;
|
||||||
int sid;
|
|
||||||
cPmtPidEntry *activePmt;
|
cPmtPidEntry *activePmt;
|
||||||
cList<cPmtPidEntry> pmtPidList;
|
cList<cPmtPidEntry> pmtPidList;
|
||||||
cList<cPmtSidEntry> pmtSidList;
|
cList<cPmtSidEntry> pmtSidList;
|
||||||
|
cList<cPmtSidRequest> pmtSidRequestList;
|
||||||
|
int source;
|
||||||
|
int transponder;
|
||||||
cSectionSyncer sectionSyncer;
|
cSectionSyncer sectionSyncer;
|
||||||
|
bool TransponderChanged(void);
|
||||||
bool PmtPidComplete(int PmtPid);
|
bool PmtPidComplete(int PmtPid);
|
||||||
void PmtPidReset(int PmtPid);
|
void PmtPidReset(int PmtPid);
|
||||||
bool PmtVersionChanged(int PmtPid, int Sid, int Version, bool SetNewVersion = false);
|
bool PmtVersionChanged(int PmtPid, int Sid, int Version, bool SetNewVersion = false);
|
||||||
|
int NumSidRequests(int Sid);
|
||||||
void SwitchToNextPmtPid(void);
|
void SwitchToNextPmtPid(void);
|
||||||
protected:
|
protected:
|
||||||
virtual void Process(u_short Pid, u_char Tid, const u_char *Data, int Length);
|
virtual void Process(u_short Pid, u_char Tid, const u_char *Data, int Length);
|
||||||
public:
|
public:
|
||||||
cPatFilter(void);
|
cPatFilter(void);
|
||||||
virtual void SetStatus(bool On);
|
void Trigger(int); // triggers reading the PMT PIDs that are currently not requested (dummy parameter for backwards compatibility, value is ignored)
|
||||||
void Trigger(int Sid = -1);
|
void Request(int Sid); // requests permanent reading of the PMT PID for this SID
|
||||||
|
void Release(int Sid); // releases permanent reading of the PMT PID for this SID
|
||||||
};
|
};
|
||||||
|
|
||||||
void GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, cDynamicBuffer &Buffer, int EsPid);
|
void GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, cDynamicBuffer &Buffer, int EsPid);
|
||||||
|
Loading…
Reference in New Issue
Block a user