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 cutter should only increment the TS continuity counter for
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>
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
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
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.
- The cutter now only increments the TS continuity counter for packets that have a
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
* 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"
@ -154,8 +154,10 @@ bool cDanglingPacketStripper::Process(uchar *Data, int Length, int64_t FirstPts)
class cPtsFixer {
private:
int delta; // time between two frames
int64_t last; // the last (i.e. highest) video PTS value seen
int64_t offset; // offset to add to PTS values
int64_t deltaDts; // the difference between two consecutive DTS values (may differ from 'delta' in case of multiple fields per frame)
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)
uchar counter[MAXPID]; // the TS continuity counter for each PID
cPatPmtParser patPmtParser;
@ -168,7 +170,9 @@ public:
cPtsFixer::cPtsFixer(void)
{
delta = 0;
last = -1;
deltaDts = 0;
lastPts = -1;
lastDts = -1;
offset = -1;
fixCounters = false;
memset(counter, 0x00, sizeof(counter));
@ -186,11 +190,11 @@ void cPtsFixer::Fix(uchar *Data, int Length, bool CutIn)
return;
}
// 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);
if (Pts >= 0) {
// offset is calculated so that Pts + offset results in last + delta:
offset = Pts - PtsAdd(last, delta);
// offset is calculated so that Pts + offset results in lastPts + delta:
offset = Pts - PtsAdd(lastPts, delta);
if (offset <= 0)
offset = -offset;
else
@ -199,14 +203,32 @@ void cPtsFixer::Fix(uchar *Data, int Length, bool CutIn)
fixCounters = true;
}
// Keep track of the highest video PTS:
bool GotPts = false;
int64_t PrevDts = lastDts;
uchar *p = Data;
int len = Length;
while (len >= TS_SIZE && *p == TS_SYNC_BYTE) {
int Pid = TsPid(p);
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 (Pts >= 0 && (last < 0 || PtsDiff(last, Pts) > 0))
last = Pts;
if (!GotPts) { // in case of multiple fields per frame, the offset is calculated only with the first one
int64_t Pts = TsGetPts(p, TS_SIZE);
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:
if (fixCounters) {
@ -229,8 +251,14 @@ void cPtsFixer::Fix(uchar *Data, int Length, bool CutIn)
if (Pts >= 0)
TsSetPts(p, TS_SIZE, PtsAdd(Pts, offset));
int64_t Dts = TsGetDts(p, TS_SIZE);
if (Dts >= 0)
TsSetDts(p, TS_SIZE, PtsAdd(Dts, offset));
if (Dts >= 0) {
if (CutIn) {
lastDts = PtsAdd(lastDts, deltaDts);
TsSetDts(p, TS_SIZE, lastDts);
}
else
TsSetDts(p, TS_SIZE, PtsAdd(Dts, offset));
}
int64_t Pcr = TsGetPcr(p);
if (Pcr >= 0) {
int64_t NewPcr = Pcr + offset * PCRFACTOR;
@ -242,6 +270,7 @@ void cPtsFixer::Fix(uchar *Data, int Length, bool CutIn)
len -= TS_SIZE;
}
}
lastDts = PrevDts;
}
// --- cCuttingThread --------------------------------------------------------