@@ -210,7 +210,7 @@ int cPesAssembler::PacketSize(const ucha
#define DEFAULTPRIORITY -1
// The minimum number of unknown PS1 packets to consider this a "pre 1.3.19 private stream":
-#define MIN_PRE_1_3_19_PRIVATESTREAM 10
+#define MIN_PRE_1_3_19_PRIVATESTREAM 0 /*10*/
int cDevice::numDevices = 0;
int cDevice::useDevice = 0;
@@ -1387,6 +1387,51 @@ int cDolbyRepacker::BreakAt(const uchar
return -1;
}
+class cLogger {
+ static int instance;
+ FILE *logFileTS;
+ FILE *logFilePES;
+ static void Store(FILE *LogFile, const uchar *Data, int Count);
+public:
+ cLogger(void);
+ ~cLogger();
+ void PutTS(const uchar *Data) { Store(logFileTS, Data, 188); }
+ void PutPES(const uchar *Data, int Count) { Store(logFilePES, Data, Count); }
+ };
+
+int cLogger::instance = 0;
+
+cLogger::cLogger(void)
+{
+ int Instance = instance++;
+ char FileNameTS[200];
+ sprintf(FileNameTS, "/video/subtitle_log_%d_%02d.ts", getpid(), Instance);
+ logFileTS = fopen(FileNameTS, "wb");
+ char FileNamePES[200];
+ sprintf(FileNamePES, "/video/subtitle_log_%d_%02d.pes", getpid(), Instance);
+ logFilePES = fopen(FileNamePES, "wb");
+}
+
+cLogger::~cLogger()
+{
+ fclose(logFileTS);
+ fclose(logFilePES);
+}
+
+#include <sys/time.h>
+#include "device.h"
+
+void cLogger::Store(FILE *LogFile, const uchar *Data, int Count)
+{
+ timeval tv;
+ gettimeofday(&tv, 0);
+ int64_t stc = cDevice::PrimaryDevice()->GetSTC();
+ fwrite(&tv, sizeof (tv), 1, LogFile);
+ fwrite(&stc, sizeof (stc), 1, LogFile);
+ fwrite(Data, Count, 1, LogFile);
+ fflush(LogFile);
+}
+
// --- cTS2PES ---------------------------------------------------------------
#include <netinet/in.h>
@@ -1474,12 +1519,14 @@ public:
int Pid(void) { return pid; }
void ts_to_pes(const uint8_t *Buf); // don't need count (=188)
void Clear(void);
+cLogger *logger;
};
uint8_t cTS2PES::headr[] = { 0x00, 0x00, 0x01 };
cTS2PES::cTS2PES(int Pid, cRingBufferLinear *ResultBuffer, int Size, uint8_t RewriteCid, uint8_t SubStreamId, cRepacker *Repacker)
{
+logger = (Repacker ? 0 : new cLogger);
pid = Pid;
resultBuffer = ResultBuffer;
size = Size;
@@ -1504,6 +1551,7 @@ cTS2PES::cTS2PES(int Pid, cRingBufferLin
cTS2PES::~cTS2PES()
{
+delete logger;
if (tsErrors || ccErrors)
dsyslog("cTS2PES got %d TS errors, %d TS continuity errors", tsErrors, ccErrors);
free(buf);
@@ -1519,6 +1567,7 @@ void cTS2PES::Clear(void)
void cTS2PES::store(uint8_t *Data, int Count)
{
+if (logger) logger->PutPES(Data, Count);
if (repacker)
repacker->Repack(resultBuffer, Data, Count);
else
@@ -1749,14 +1798,15 @@ void cTS2PES::instant_repack(const uint8
case AUDIO_STREAM_S ... AUDIO_STREAM_E:
case VIDEO_STREAM_S ... VIDEO_STREAM_E:
case PRIVATE_STREAM1:
-
- if (mpeg == 2 && found == 9) {
+ /* make sure to not write the data twice by looking at count */
+ if (mpeg == 2 && found == 9 && count < found) {
write_ipack(&flag1, 1);
write_ipack(&flag2, 1);
write_ipack(&hlength, 1);
}
- if (mpeg == 1 && found == mpeg1_required) {
+ /* make sure to not write the data twice by looking at count */
+ if (mpeg == 1 && found == mpeg1_required && count < found) {
write_ipack(&flag1, 1);
if (mpeg1_required > 7) {
write_ipack(&flag2, 1);
@@ -1826,7 +1876,7 @@ void cTS2PES::ts_to_pes(const uint8_t *B
{
if (!Buf)
return;
-
+if (logger) logger->PutTS(Buf);
if (Buf[1] & TS_ERROR)
tsErrors++;
@@ -1883,7 +1933,7 @@ cRemux::cRemux(int VPid, const int *APid
skipped = 0;
numTracks = 0;
resultSkipped = 0;
- resultBuffer = new cRingBufferLinear(RESULTBUFFERSIZE, IPACKS, false, "Result");
+ resultBuffer = new cRingBufferLinear(RESULTBUFFERSIZE, IPACKS, false, "Result", true);
resultBuffer->SetTimeouts(0, 100);
if (VPid)
#define TEST_cVideoRepacker
@@ -1912,7 +1962,7 @@ cRemux::cRemux(int VPid, const int *APid
if (SPids) {
int n = 0;
while (*SPids && numTracks < MAXTRACKS && n < MAXSPIDS)
- ts2pes[numTracks++] = new cTS2PES(*SPids++, resultBuffer, SUBTITLE_PACKS, 0x00, 0x20 + n++);
+ ts2pes[numTracks++] = new cTS2PES(*SPids++, resultBuffer, IPACKS /*SUBTITLE_PACKS*/, 0x00, 0x20 + n++);
}
}
@@ -151,9 +151,10 @@ void cRingBufferLinear::PrintDebugRBL(vo
}
#endif
-cRingBufferLinear::cRingBufferLinear(int Size, int Margin, bool Statistics, const char *Description)
+cRingBufferLinear::cRingBufferLinear(int Size, int Margin, bool Statistics, const char *Description, bool AssumePesContent)
:cRingBuffer(Size, Statistics)
{
+ assumePesContent = AssumePesContent;
description = Description ? strdup(Description) : NULL;
tail = head = margin = Margin;
gotten = 0;
@@ -299,7 +300,7 @@ uchar *cRingBufferLinear::Get(int &Count
int cont = (diff >= 0) ? diff : Size() + diff - margin;
if (cont > rest)
cont = rest;
- if (cont >= margin) {
+ if (cont >= margin || assumePesContent && HasPesPacket(cont)) {
p = buffer + tail;
Count = gotten = cont;
}
@@ -308,6 +309,19 @@ uchar *cRingBufferLinear::Get(int &Count
return p;
}
+bool cRingBufferLinear::HasPesPacket(int &Count)
+{
+ uchar *p = buffer + tail;
+ if (Count >= 6 && !p[0] && !p[1] && p[2] == 0x01) {
+ int Length = 6 + p[4] * 256 + p[5];
+ if (Length <= Count) {
+ Count = Length;
+ return true;
+ }
+ }
+ return false;
+}
+
void cRingBufferLinear::Del(int Count)
{
if (Count > gotten) {
@@ -60,12 +60,17 @@ private:
int gotten;
uchar *buffer;
char *description;
+ bool assumePesContent;
+ bool HasPesPacket(int &Count);
public:
- cRingBufferLinear(int Size, int Margin = 0, bool Statistics = false, const char *Description = NULL);
+ cRingBufferLinear(int Size, int Margin = 0, bool Statistics = false, const char *Description = NULL, bool AssumePesContent = false);
///< Creates a linear ring buffer.
///< The buffer will be able to hold at most Size-Margin-1 bytes of data, and will
///< be guaranteed to return at least Margin bytes in one consecutive block.
///< The optional Description is used for debugging only.
+ ///< AssumePesContent specializes the buffer and changes its behavior when less
+ ///< than Margin bytes are available. The buffer is then allowed to return at
+ ///< least a complete PES packet.
virtual ~cRingBufferLinear();
virtual int Available(void);
virtual int Free(void) { return Size() - Available() - 1 - margin; }