index.vdr misses pictures
Commit Message
Hi,
Werner wrote:
>>>in recent recording from premiere i saw that not all pictures in
>>>the data stream are indexed in index.vdr. The displayed movie lenghts are
>>>slightly to short and the cutmarks in marks.vdr are wrong. I use
>>>marks.vdr in an external program. The resulting cutted movies are
>>>sometimes about 1-2 minutes too short. This does not affect normal
>>>vdr users too much because vdr cutted movies have the right len.
>>>
>>>Im not an mpeg expert, so only some speculations:
>>>It looks that every index.vdr entry points to an "packet start code"
>>>(0x000001). Vdr assumes that every packet has mostly one picture start
>>>code. The difference i saw between old recordings and new recordings
>>>is that in new recordings are sometimes two picture start codes in a
>>>packet. The second one is dropped by vdr.
>>>I have no idea of how to fix this assuming that vdr can only resume
>>>on a packet start code. Anyone any idea?
>>
>>If you were right, then cVideoRepacker is buggy. Are you shure that you
>>see two picture start codes (0x00000100) in one PES-Packet?
>
> yes, thats what i saw. My app demuxes the data stream (with the help
> of some libmpeg2 code) and two printfs show that sometimes (<5%) there are
> two picture start codes in a packet.
In the sample you sent me, there really are two picture start codes in
one PES packet. You've already got the attached patch which records a
snipplet of the TS stream in such a case.
Do you already have some test material, as I'm ready to replay and debug it?
Bye.
@@ -33,9 +33,11 @@ ePesHeader AnalyzePesHeader(const uchar
#define MAXTRACKS 64
class cTS2PES;
+class cTSLogger;
class cRemux {
private:
+cTSLogger *tsLogger;
bool exitOnFailure;
bool isRadio;
int numUPTerrors;
@@ -65,6 +67,7 @@ public:
int Put(const uchar *Data, int Count);
///< Puts at most Count bytes of Data into the remuxer.
///< \return Returns the number of bytes actually consumed from Data.
+ uchar *Get0(int &Count, uchar *PictureType = NULL);
uchar *Get(int &Count, uchar *PictureType = NULL);
///< Gets all currently available data from the remuxer.
///< \return Count contains the number of bytes the result points to, and
@@ -86,6 +86,60 @@ ePesHeader AnalyzePesHeader(const uchar
return phMPEG1; // MPEG 1
}
+// --- cTSLogger -------------------------------------------------------------
+
+class cTSLogger
+{
+ uchar *buffer;
+ int size;
+ int fill;
+ int64_t count;
+ int dumps;
+ int cid;
+
+public:
+ cTSLogger(int Cid);
+ ~cTSLogger();
+ void Put(const uchar *Data);
+ void Dump();
+};
+
+cTSLogger::cTSLogger(int Cid)
+{
+ size = 1000; // number of TS packets to log
+ buffer = new uchar[size * 188];
+ fill = 0;
+ count = 0;
+ dumps = 0;
+ cid = Cid;
+}
+
+cTSLogger::~cTSLogger()
+{
+ delete [] buffer;
+}
+
+void cTSLogger::Put(const uchar *Data)
+{
+ memcpy(&buffer[(count++ % size) * 188], Data, 188);
+ if (fill < size)
+ fill++;
+}
+
+void cTSLogger::Dump()
+{
+ char name[200];
+ sprintf(name, "/video/ts_%d_%ld_0x%02X_%03d_%lld_%d.log", getpid(), pthread_self(), cid, dumps++, count, fill);
+ esyslog("cTSLogger: dumping to file '%s'", name);
+
+ FILE *f = fopen(name, "wb");
+ for (int64_t n = count - fill; n < count; n++)
+ fwrite(&buffer[(n % size) * 188], 188, 1, f);
+ fclose(f);
+
+ fill = 0;
+}
+
// --- cRepacker -------------------------------------------------------------
class cRepacker {
@@ -1675,6 +1731,7 @@ void cTS2PES::ts_to_pes(const uint8_t *B
cRemux::cRemux(int VPid, const int *APids, const int *DPids, const int *SPids, bool ExitOnFailure)
{
+tsLogger = new cTSLogger(0xe0);
exitOnFailure = ExitOnFailure;
isRadio = VPid == 0 || VPid == 1 || VPid == 0x1FFF;
numUPTerrors = 0;
@@ -1722,6 +1779,7 @@ cRemux::~cRemux()
for (int t = 0; t < numTracks; t++)
delete ts2pes[t];
delete resultBuffer;
+delete tsLogger;
}
int cRemux::GetPid(const uchar *Data)
@@ -1793,6 +1851,7 @@ int cRemux::Put(const uchar *Data, int C
if (Data[i + 3] & 0x10) { // got payload
for (int t = 0; t < numTracks; t++) {
if (ts2pes[t]->Pid() == pid) {
+if (t == 0) tsLogger->Put(Data + i);
ts2pes[t]->ts_to_pes(Data + i);
break;
}
@@ -1818,6 +1877,52 @@ int cRemux::Put(const uchar *Data, int C
uchar *cRemux::Get(int &Count, uchar *PictureType)
{
+ uchar *r = Get0(Count, PictureType);
+
+ int n = 0;
+ while (r && n < Count)
+ {
+ if (r[ n + 0 ] != 0x00
+ || r[ n + 1 ] != 0x00
+ || r[ n + 2 ] != 0x01)
+ {
+ esyslog("out of sync ======================");
+ break;
+ }
+
+ int l = 6 + r[ n + 4 ] * 256 + r[ n + 5 ];
+ if ((r[ n + 3 ] & 0xf0) != 0xe0)
+ {
+ n += l;
+ continue;
+ }
+
+ ulong scanner = 0xffffffff;
+ int k = 0;
+
+ int o = 6 + 3 + r[ n + 8 ];
+ for (int i = o; i < l; i++)
+ {
+ scanner <<= 8;
+ scanner |= r[ n + i ];
+
+ if (scanner == 0x00000100)
+ {
+ k++;
+
+ if (k > 1)
+ tsLogger->Dump();
+ }
+ }
+
+ n += l;
+ }
+
+ return r;
+}
+
+uchar *cRemux::Get0(int &Count, uchar *PictureType)
+{
// Remove any previously skipped data from the result buffer:
if (resultSkipped > 0) {