summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKlaus Schmidinger <vdr@tvdr.de>2017-03-26 13:07:01 +0200
committerKlaus Schmidinger <vdr@tvdr.de>2017-03-26 13:07:01 +0200
commitb313d88db13d1e90f81f9967af1fba8c8f84e59d (patch)
tree7f97ed5e6ca7727bb52ff4ca016125b60e96fe8b
parent9e808255f842067e0c0c9ee2344f6c1aa2860e08 (diff)
downloadvdr-b313d88db13d1e90f81f9967af1fba8c8f84e59d.tar.gz
vdr-b313d88db13d1e90f81f9967af1fba8c8f84e59d.tar.bz2
Improved clearing the MTD buffer and syncing on TS packets
-rw-r--r--device.c9
-rw-r--r--mtd.c23
-rw-r--r--mtd.h4
-rw-r--r--remux.c22
-rw-r--r--remux.h11
5 files changed, 45 insertions, 24 deletions
diff --git a/device.c b/device.c
index 6f3a155d..ccd0e20a 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 4.9 2017/03/23 14:19:59 kls Exp $
+ * $Id: device.c 4.10 2017/03/26 11:35:38 kls Exp $
*/
#include "device.h"
@@ -1570,13 +1570,8 @@ int cDevice::PlayTs(const uchar *Data, int Length, bool VideoOnly)
}
else {
while (Length >= TS_SIZE) {
- if (Data[0] != TS_SYNC_BYTE) {
- int Skipped = 1;
- while (Skipped < Length && (Data[Skipped] != TS_SYNC_BYTE || Length - Skipped > TS_SIZE && Data[Skipped + TS_SIZE] != TS_SYNC_BYTE))
- Skipped++;
- esyslog("ERROR: skipped %d bytes to sync on start of TS packet", Skipped);
+ if (int Skipped = TS_SYNC(Data, Length))
return Played + Skipped;
- }
int Pid = TsPid(Data);
if (TsHasPayload(Data)) { // silently ignore TS packets w/o payload
int PayloadOffset = TsPayloadOffset(Data);
diff --git a/mtd.c b/mtd.c
index 2fa55626..a170cbc9 100644
--- a/mtd.c
+++ b/mtd.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: mtd.c 1.5 2017/03/25 14:09:31 kls Exp $
+ * $Id: mtd.c 1.6 2017/03/26 13:01:32 kls Exp $
*/
#include "mtd.h"
@@ -229,7 +229,6 @@ cMtdCamSlot::cMtdCamSlot(cCamSlot *MasterSlot, int Index)
mtdBuffer = new cRingBufferLinear(MTD_BUFFER_SIZE, TS_SIZE, true, "MTD buffer");
mtdMapper = new cMtdMapper(Index + 1, MasterSlot->SlotNumber());
delivered = false;
- clearBuffer = false;
ciAdapter = MasterSlot->ciAdapter; // we don't pass the CI adapter in the constructor, to prevent this one from being inserted into CamSlots
}
@@ -279,8 +278,10 @@ void cMtdCamSlot::StopDecrypting(void)
cCamSlot::StopDecrypting();
if (!MasterSlot()->IsDecrypting())
MasterSlot()->StopDecrypting();
+ cMutexLock MutexLock(&mutex);
mtdMapper->Clear();
- clearBuffer = true;
+ mtdBuffer->Clear();
+ delivered = false;
}
uchar *cMtdCamSlot::Decrypt(uchar *Data, int &Count)
@@ -297,18 +298,19 @@ uchar *cMtdCamSlot::Decrypt(uchar *Data, int &Count)
else
Count = 0;
// Drop delivered data from previous call:
+ cMutexLock MutexLock(&mutex);
if (delivered) {
mtdBuffer->Del(TS_SIZE);
delivered = false;
}
- if (clearBuffer) {
- mtdBuffer->Clear();
- clearBuffer = false;
- }
// Receive data from buffer:
int c = 0;
uchar *d = mtdBuffer->Get(c);
if (d) {
+ if (int Skipped = TS_SYNC(d, c)) {
+ mtdBuffer->Del(Skipped);
+ return NULL;
+ }
if (c >= TS_SIZE) {
TsSetPid(d, mtdMapper->UniqToRealPid(TsPid(d)));
delivered = true;
@@ -321,6 +323,13 @@ uchar *cMtdCamSlot::Decrypt(uchar *Data, int &Count)
int cMtdCamSlot::PutData(const uchar *Data, int Count)
{
+ cMutexLock MutexLock(&mutex);
+ int Free = mtdBuffer->Free();
+ Free -= Free % TS_SIZE;
+ if (Free < TS_SIZE)
+ return 0;
+ if (Free < Count)
+ Count = Free;
return mtdBuffer->Put(Data, Count);
}
diff --git a/mtd.h b/mtd.h
index 15d29b83..ea62f426 100644
--- a/mtd.h
+++ b/mtd.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: mtd.h 1.4 2017/03/23 12:48:22 kls Exp $
+ * $Id: mtd.h 1.5 2017/03/25 14:47:03 kls Exp $
*/
#ifndef __MTD_H
@@ -151,10 +151,10 @@ void MtdMapPid(uchar *p, cMtdMapper *MtdMapper);
class cMtdCamSlot : public cCamSlot {
private:
+ cMutex mutex;
cMtdMapper *mtdMapper;
cRingBufferLinear *mtdBuffer;
bool delivered;
- bool clearBuffer;
protected:
virtual const int *GetCaSystemIds(void);
virtual void SendCaPmt(uint8_t CmdId);
diff --git a/remux.c b/remux.c
index cb694760..a2d2dd6c 100644
--- a/remux.c
+++ b/remux.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: remux.c 4.4 2017/01/09 15:05:05 kls Exp $
+ * $Id: remux.c 4.5 2017/03/26 13:07:01 kls Exp $
*/
#include "remux.h"
@@ -144,6 +144,19 @@ void TsSetPcr(uchar *p, int64_t Pcr)
}
}
+int TsSync(const uchar *Data, int Length, const char *File, const char *Function, int Line)
+{
+ int Skipped = 0;
+ while (Length > 0 && (*Data != TS_SYNC_BYTE || Length > TS_SIZE && Data[TS_SIZE] != TS_SYNC_BYTE)) {
+ Data++;
+ Length--;
+ Skipped++;
+ }
+ if (Skipped && File && Function && Line)
+ esyslog("ERROR: skipped %d bytes to sync on start of TS packet at %s/%s(%d)", Skipped, File, Function, Line);
+ return Skipped;
+}
+
int64_t TsGetPts(const uchar *p, int l)
{
// Find the first packet with a PTS and use it:
@@ -1557,13 +1570,8 @@ int cFrameDetector::Analyze(const uchar *Data, int Length)
newFrame = independentFrame = false;
while (Length >= MIN_TS_PACKETS_FOR_FRAME_DETECTOR * TS_SIZE) { // makes sure we are looking at enough data, in case the frame type is not stored in the first TS packet
// Sync on TS packet borders:
- if (Data[0] != TS_SYNC_BYTE) {
- int Skipped = 1;
- while (Skipped < Length && (Data[Skipped] != TS_SYNC_BYTE || Length - Skipped > TS_SIZE && Data[Skipped + TS_SIZE] != TS_SYNC_BYTE))
- Skipped++;
- esyslog("ERROR: skipped %d bytes to sync on start of TS packet", Skipped);
+ if (int Skipped = TS_SYNC(Data, Length))
return Processed + Skipped;
- }
// Handle one TS packet:
int Handled = TS_SIZE;
if (TsHasPayload(Data) && !TsIsScrambled(Data)) {
diff --git a/remux.h b/remux.h
index 28dfde4b..7dd5b163 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 4.2 2017/02/27 16:11:57 kls Exp $
+ * $Id: remux.h 4.3 2017/03/26 13:06:37 kls Exp $
*/
#ifndef __REMUX_H
@@ -144,6 +144,15 @@ inline int64_t TsGetPcr(const uchar *p)
void TsHidePayload(uchar *p);
void TsSetPcr(uchar *p, int64_t Pcr);
+// Helper macro and function to quickly check whether Data points to the beginning
+// of a TS packet. The return value is the number of bytes that need to be skipped
+// to synchronize on the next TS packet (zero if already sync'd). TsSync() can be
+// called directly, the macro just performs the initial check inline and adds some
+// debug information for logging.
+
+#define TS_SYNC(Data, Length) (*Data == TS_SYNC_BYTE ? 0 : TsSync(Data, Length, __FILE__, __FUNCTION__, __LINE__))
+int TsSync(const uchar *Data, int Length, const char *File = NULL, const char *Function = NULL, int Line = 0);
+
// The following functions all take a pointer to a sequence of complete TS packets.
int64_t TsGetPts(const uchar *p, int l);