Fixed adjusting the DTS values in the cutter, to compensate for dropped B-frames

This commit is contained in:
Klaus Schmidinger 2012-11-29 15:34:55 +01:00
parent 2eadd7d4dd
commit b73c83e2a1
3 changed files with 46 additions and 13 deletions

View File

@ -2975,6 +2975,8 @@ S
for pointing out that the name H264 should be used instead of MPEG4 for pointing out that the name H264 should be used instead of MPEG4
for pointing out that the cutter should only increment the TS continuity counter for for pointing out that the cutter should only increment the TS continuity counter for
packets that have a payload packets that have a payload
for pointing out that when adjusting the DTS values in the cutter, it hase to compensate
for dropped B-frames
Peter Münster <pmlists@free.fr> Peter Münster <pmlists@free.fr>
for fixing 'make install' to not overwrite existing configuration files for fixing 'make install' to not overwrite existing configuration files

View File

@ -7339,7 +7339,7 @@ Video Disk Recorder Revision History
- Modified editing marks are now written to disk whenever the replay progress display - Modified editing marks are now written to disk whenever the replay progress display
gets hidden (thanks to Christoph Haubrich). gets hidden (thanks to Christoph Haubrich).
2012-11-27: Version 1.7.33 2012-11-29: Version 1.7.33
- In order to be able to play TS recordings from other sources, in which there is - In order to be able to play TS recordings from other sources, in which there is
more than one PMT PID in the PAT, 'int cPatPmtParser::PatPmt(void)' has been changed more than one PMT PID in the PAT, 'int cPatPmtParser::PatPmt(void)' has been changed
@ -7353,3 +7353,5 @@ Video Disk Recorder Revision History
end mark. end mark.
- The cutter now only increments the TS continuity counter for packets that have a - The cutter now only increments the TS continuity counter for packets that have a
payload (pointed out by Sören Moch). payload (pointed out by Sören Moch).
- Fixed adjusting the DTS values in the cutter, to compensate for dropped B-frames
(pointed out by Sören Moch).

View File

@ -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: cutter.c 2.19 2012/11/26 17:21:14 kls Exp $ * $Id: cutter.c 2.20 2012/11/29 15:30:01 kls Exp $
*/ */
#include "cutter.h" #include "cutter.h"
@ -154,8 +154,10 @@ bool cDanglingPacketStripper::Process(uchar *Data, int Length, int64_t FirstPts)
class cPtsFixer { class cPtsFixer {
private: private:
int delta; // time between two frames int delta; // time between two frames
int64_t last; // the last (i.e. highest) video PTS value seen int64_t deltaDts; // the difference between two consecutive DTS values (may differ from 'delta' in case of multiple fields per frame)
int64_t offset; // offset to add to PTS values int64_t lastPts; // the video PTS of the last frame (in display order)
int64_t lastDts; // the last video DTS value seen
int64_t offset; // offset to add to all timestamps
bool fixCounters; // controls fixing the TS continuity counters (only from the second CutIn up) bool fixCounters; // controls fixing the TS continuity counters (only from the second CutIn up)
uchar counter[MAXPID]; // the TS continuity counter for each PID uchar counter[MAXPID]; // the TS continuity counter for each PID
cPatPmtParser patPmtParser; cPatPmtParser patPmtParser;
@ -168,7 +170,9 @@ public:
cPtsFixer::cPtsFixer(void) cPtsFixer::cPtsFixer(void)
{ {
delta = 0; delta = 0;
last = -1; deltaDts = 0;
lastPts = -1;
lastDts = -1;
offset = -1; offset = -1;
fixCounters = false; fixCounters = false;
memset(counter, 0x00, sizeof(counter)); memset(counter, 0x00, sizeof(counter));
@ -186,11 +190,11 @@ void cPtsFixer::Fix(uchar *Data, int Length, bool CutIn)
return; return;
} }
// Determine the PTS offset at the beginning of each sequence (except the first one): // Determine the PTS offset at the beginning of each sequence (except the first one):
if (CutIn && last >= 0) { if (CutIn && lastPts >= 0) {
int64_t Pts = TsGetPts(Data, Length); int64_t Pts = TsGetPts(Data, Length);
if (Pts >= 0) { if (Pts >= 0) {
// offset is calculated so that Pts + offset results in last + delta: // offset is calculated so that Pts + offset results in lastPts + delta:
offset = Pts - PtsAdd(last, delta); offset = Pts - PtsAdd(lastPts, delta);
if (offset <= 0) if (offset <= 0)
offset = -offset; offset = -offset;
else else
@ -199,14 +203,32 @@ void cPtsFixer::Fix(uchar *Data, int Length, bool CutIn)
fixCounters = true; fixCounters = true;
} }
// Keep track of the highest video PTS: // Keep track of the highest video PTS:
bool GotPts = false;
int64_t PrevDts = lastDts;
uchar *p = Data; uchar *p = Data;
int len = Length; int len = Length;
while (len >= TS_SIZE && *p == TS_SYNC_BYTE) { while (len >= TS_SIZE && *p == TS_SYNC_BYTE) {
int Pid = TsPid(p); int Pid = TsPid(p);
if (Pid == patPmtParser.Vpid()) { if (Pid == patPmtParser.Vpid()) {
int64_t Pts = PtsAdd(TsGetPts(p, TS_SIZE), offset); // offset is taken into account here, to make last have the "new" value already! if (!GotPts) { // in case of multiple fields per frame, the offset is calculated only with the first one
if (Pts >= 0 && (last < 0 || PtsDiff(last, Pts) > 0)) int64_t Pts = TsGetPts(p, TS_SIZE);
last = Pts; if (Pts >= 0) {
if (offset >= 0)
Pts = PtsAdd(Pts, offset); // offset is taken into account here, to make lastPts have the "new" value already!
if (lastPts < 0 || PtsDiff(lastPts, Pts) > 0)
lastPts = Pts;
}
GotPts = true;
}
if (!CutIn) {
int64_t Dts = TsGetDts(p, TS_SIZE);
if (Dts >= 0) {
if (offset >= 0)
Dts = PtsAdd(Dts, offset); // offset is taken into account here, to make lastDts have the "new" value already!
deltaDts = PtsDiff(PrevDts, Dts);
PrevDts = Dts;
}
}
} }
// Adjust the TS continuity counter: // Adjust the TS continuity counter:
if (fixCounters) { if (fixCounters) {
@ -229,8 +251,14 @@ void cPtsFixer::Fix(uchar *Data, int Length, bool CutIn)
if (Pts >= 0) if (Pts >= 0)
TsSetPts(p, TS_SIZE, PtsAdd(Pts, offset)); TsSetPts(p, TS_SIZE, PtsAdd(Pts, offset));
int64_t Dts = TsGetDts(p, TS_SIZE); int64_t Dts = TsGetDts(p, TS_SIZE);
if (Dts >= 0) if (Dts >= 0) {
TsSetDts(p, TS_SIZE, PtsAdd(Dts, offset)); if (CutIn) {
lastDts = PtsAdd(lastDts, deltaDts);
TsSetDts(p, TS_SIZE, lastDts);
}
else
TsSetDts(p, TS_SIZE, PtsAdd(Dts, offset));
}
int64_t Pcr = TsGetPcr(p); int64_t Pcr = TsGetPcr(p);
if (Pcr >= 0) { if (Pcr >= 0) {
int64_t NewPcr = Pcr + offset * PCRFACTOR; int64_t NewPcr = Pcr + offset * PCRFACTOR;
@ -242,6 +270,7 @@ void cPtsFixer::Fix(uchar *Data, int Length, bool CutIn)
len -= TS_SIZE; len -= TS_SIZE;
} }
} }
lastDts = PrevDts;
} }
// --- cCuttingThread -------------------------------------------------------- // --- cCuttingThread --------------------------------------------------------