1
0
mirror of https://github.com/VDR4Arch/vdr.git synced 2023-10-10 13:36:52 +02:00

Replaced cBackTrace with cPtsIndex

This commit is contained in:
Klaus Schmidinger 2009-03-13 14:45:12 +01:00
parent 4c0ab3d3e7
commit e7ea3b3c70
9 changed files with 186 additions and 110 deletions

View File

@ -662,6 +662,8 @@ Oliver Endriss <o.endriss@gmx.de>
Transfer Mode Transfer Mode
for providing a driver patch that allows direct replaying of TS video on full-featured for providing a driver patch that allows direct replaying of TS video on full-featured
DVB cards DVB cards
for improving the firmware of FF DVB cards to allow getting the current STC value
even in trick modes
Reinhard Walter Buchner <rw.buchner@freenet.de> Reinhard Walter Buchner <rw.buchner@freenet.de>
for adding some satellites to 'sources.conf' for adding some satellites to 'sources.conf'

13
HISTORY
View File

@ -5979,7 +5979,7 @@ Video Disk Recorder Revision History
cDevice class reimplements PlayTs() or PlayPes(), it also needs to make sure this cDevice class reimplements PlayTs() or PlayPes(), it also needs to make sure this
new function works as expected. new function works as expected.
2009-02-28: Version 1.7.5 2009-03-13: Version 1.7.5
- Fixed a hangup when replaying a TS recording with subtitles activated (reported - Fixed a hangup when replaying a TS recording with subtitles activated (reported
by Timo Helkio). by Timo Helkio).
@ -5989,3 +5989,14 @@ Video Disk Recorder Revision History
Ahrenberg). Ahrenberg).
- Updated the Italian OSD texts (thanks to Diego Pierotto). - Updated the Italian OSD texts (thanks to Diego Pierotto).
- Added cRecordingInfo::GetEvent() (thanks to Marcel Unbehaun). - Added cRecordingInfo::GetEvent() (thanks to Marcel Unbehaun).
- Improved synchronizing the progress display, trick modes and subtitle display
to the actual audio/video. This now works independent of any buffer sizes the
output device might use.
+ The cBackTrace class has been replaced with cPtsIndex, which keeps track
of the PTS timestamps of recently played frames.
+ cDevice::GetSTC() is now required to deliver the STC even in trick modes.
It is sufficient if it returns the PTS of the most recently presented
audio/video frame.
+ The full-featured DVB cards need an improved firmware in order to return
proper STC values in trick modes (thanks to Oliver Endriss for enhancing the
av7110 firmware).

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: device.h 2.6 2009/01/25 11:04:39 kls Exp $ * $Id: device.h 2.7 2009/03/01 11:20:34 kls Exp $
*/ */
#ifndef __DEVICE_H #ifndef __DEVICE_H
@ -543,6 +543,13 @@ public:
///< Gets the current System Time Counter, which can be used to ///< Gets the current System Time Counter, which can be used to
///< synchronize audio and video. If this device is unable to ///< synchronize audio and video. If this device is unable to
///< provide the STC, -1 will be returned. ///< provide the STC, -1 will be returned.
///< The value returned doesn't need to be an actual "clock" value,
///< it is sufficient if it holds the PTS (Presentation Time Stamp) of
///< the most recently presented frame. A proper value must be returned
///< in normal replay mode as well as in any trick modes (like slow motion,
///< fast forward/rewind).
///< Only the lower 32 bit of this value are actually used, since some
///< devices can't handle the msb correctly.
virtual bool IsPlayingVideo(void) const { return isPlayingVideo; } virtual bool IsPlayingVideo(void) const { return isPlayingVideo; }
///< \return Returns true if the currently attached player has delivered ///< \return Returns true if the currently attached player has delivered
///< any video packets. ///< any video packets.

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: dvbplayer.c 2.3 2009/01/25 11:11:39 kls Exp $ * $Id: dvbplayer.c 2.4 2009/03/13 14:42:56 kls Exp $
*/ */
#include "dvbplayer.h" #include "dvbplayer.h"
@ -16,59 +16,69 @@
#include "thread.h" #include "thread.h"
#include "tools.h" #include "tools.h"
// --- cBackTrace ------------------------------------------------------------ // --- cPtsIndex -------------------------------------------------------------
#define AVG_FRAME_SIZE 15000 // an assumption about the average frame size #define PTSINDEX_ENTRIES 100
#define DVB_BUF_SIZE (256 * 1024) // an assumption about the dvb firmware buffer size
#define BACKTRACE_ENTRIES (DVB_BUF_SIZE / AVG_FRAME_SIZE + 20) // how many entries are needed to backtrace buffer contents
class cBackTrace { class cPtsIndex {
private: private:
int index[BACKTRACE_ENTRIES]; struct tPtsIndex {
int length[BACKTRACE_ENTRIES]; uint32_t pts; // no need for 33 bit - some devices don't even supply the msb
int pos, num; int index;
};
tPtsIndex pi[PTSINDEX_ENTRIES];
int w, r;
int lastFound;
cMutex mutex;
public: public:
cBackTrace(void); cPtsIndex(void);
void Clear(void); void Clear(void);
void Add(int Index, int Length); void Put(uint32_t Pts, int Index);
int Get(bool Forward); int FindIndex(uint32_t Pts);
}; };
cBackTrace::cBackTrace(void) cPtsIndex::cPtsIndex(void)
{ {
lastFound = 0;
Clear(); Clear();
} }
void cBackTrace::Clear(void) void cPtsIndex::Clear(void)
{ {
pos = num = 0; cMutexLock MutexLock(&mutex);
w = r = 0;
} }
void cBackTrace::Add(int Index, int Length) void cPtsIndex::Put(uint32_t Pts, int Index)
{ {
index[pos] = Index; cMutexLock MutexLock(&mutex);
length[pos] = Length; pi[w].pts = Pts;
if (++pos >= BACKTRACE_ENTRIES) pi[w].index = Index;
pos = 0; w = (w + 1) % PTSINDEX_ENTRIES;
if (num < BACKTRACE_ENTRIES) if (w == r)
num++; r = (r + 1) % PTSINDEX_ENTRIES;
} }
int cBackTrace::Get(bool Forward) int cPtsIndex::FindIndex(uint32_t Pts)
{ {
int p = pos; cMutexLock MutexLock(&mutex);
int n = num; if (w == r)
int l = DVB_BUF_SIZE + (Forward ? 0 : 256 * 1024); //XXX (256 * 1024) == DVB_BUF_SIZE ??? return lastFound; // list is empty, let's not jump way off the last known position
int i = -1; uint32_t Delta = 0xFFFFFFFF;
int Index = -1;
while (n && l > 0) { for (int i = w; i != r; ) {
if (--p < 0) if (--i < 0)
p = BACKTRACE_ENTRIES - 1; i = PTSINDEX_ENTRIES - 1;
i = index[p] - 1; uint32_t d = pi[i].pts < Pts ? Pts - pi[i].pts : pi[i].pts - Pts;
l -= length[p]; if (d > 0x7FFFFFFF)
n--; d = 0xFFFFFFFF - d; // handle rollover
} if (d < Delta) {
return i; Delta = d;
Index = pi[i].index;
}
}
lastFound = Index;
return Index;
} }
// --- cNonBlockingFileReader ------------------------------------------------ // --- cNonBlockingFileReader ------------------------------------------------
@ -183,8 +193,8 @@ bool cNonBlockingFileReader::WaitForDataMs(int msToWait)
#define PLAYERBUFSIZE MEGABYTE(1) #define PLAYERBUFSIZE MEGABYTE(1)
// The number of seconds to back up when resuming an interrupted replay session: #define RESUMEBACKUP 10 // number of seconds to back up when resuming an interrupted replay session
#define RESUMEBACKUP 10 #define MAXSTUCKATEND 3 // max. number of seconds to wait in case the device doesn't play the last frame
class cDvbPlayer : public cPlayer, cThread { class cDvbPlayer : public cPlayer, cThread {
private: private:
@ -193,7 +203,7 @@ private:
static int Speeds[]; static int Speeds[];
cNonBlockingFileReader *nonBlockingFileReader; cNonBlockingFileReader *nonBlockingFileReader;
cRingBufferFrame *ringBuffer; cRingBufferFrame *ringBuffer;
cBackTrace *backTrace; cPtsIndex ptsIndex;
cFileName *fileName; cFileName *fileName;
cIndexFile *index; cIndexFile *index;
cUnbufferedFile *replayFile; cUnbufferedFile *replayFile;
@ -204,7 +214,8 @@ private:
ePlayModes playMode; ePlayModes playMode;
ePlayDirs playDir; ePlayDirs playDir;
int trickSpeed; int trickSpeed;
int readIndex, writeIndex; int readIndex;
bool readIndependent;
cFrame *readFrame; cFrame *readFrame;
cFrame *playFrame; cFrame *playFrame;
void TrickSpeed(int Increment); void TrickSpeed(int Increment);
@ -242,7 +253,6 @@ cDvbPlayer::cDvbPlayer(const char *FileName)
{ {
nonBlockingFileReader = NULL; nonBlockingFileReader = NULL;
ringBuffer = NULL; ringBuffer = NULL;
backTrace = NULL;
index = NULL; index = NULL;
cRecording Recording(FileName); cRecording Recording(FileName);
framesPerSecond = Recording.FramesPerSecond(); framesPerSecond = Recording.FramesPerSecond();
@ -252,7 +262,8 @@ cDvbPlayer::cDvbPlayer(const char *FileName)
playMode = pmPlay; playMode = pmPlay;
playDir = pdForward; playDir = pdForward;
trickSpeed = NORMAL_SPEED; trickSpeed = NORMAL_SPEED;
readIndex = writeIndex = -1; readIndex = -1;
readIndependent = false;
readFrame = NULL; readFrame = NULL;
playFrame = NULL; playFrame = NULL;
isyslog("replay %s", FileName); isyslog("replay %s", FileName);
@ -269,17 +280,15 @@ cDvbPlayer::cDvbPlayer(const char *FileName)
delete index; delete index;
index = NULL; index = NULL;
} }
backTrace = new cBackTrace;
} }
cDvbPlayer::~cDvbPlayer() cDvbPlayer::~cDvbPlayer()
{ {
Detach();
Save(); Save();
Detach();
delete readFrame; // might not have been stored in the buffer in Action() delete readFrame; // might not have been stored in the buffer in Action()
delete index; delete index;
delete fileName; delete fileName;
delete backTrace;
delete ringBuffer; delete ringBuffer;
} }
@ -308,13 +317,13 @@ void cDvbPlayer::Empty(void)
LOCK_THREAD; LOCK_THREAD;
if (nonBlockingFileReader) if (nonBlockingFileReader)
nonBlockingFileReader->Clear(); nonBlockingFileReader->Clear();
if ((readIndex = backTrace->Get(playDir == pdForward)) < 0) if (!firstPacket) // don't set the readIndex twice if Empty() is called more than once
readIndex = writeIndex; readIndex = ptsIndex.FindIndex(DeviceGetSTC());
delete readFrame; // might not have been stored in the buffer in Action() delete readFrame; // might not have been stored in the buffer in Action()
readFrame = NULL; readFrame = NULL;
playFrame = NULL; playFrame = NULL;
ringBuffer->Clear(); ringBuffer->Clear();
backTrace->Clear(); ptsIndex.Clear();
DeviceClear(); DeviceClear();
firstPacket = true; firstPacket = true;
} }
@ -346,7 +355,7 @@ int cDvbPlayer::Resume(void)
bool cDvbPlayer::Save(void) bool cDvbPlayer::Save(void)
{ {
if (index) { if (index) {
int Index = writeIndex; int Index = ptsIndex.FindIndex(DeviceGetSTC());
if (Index >= 0) { if (Index >= 0) {
Index -= int(round(RESUMEBACKUP * framesPerSecond)); Index -= int(round(RESUMEBACKUP * framesPerSecond));
if (Index > 0) if (Index > 0)
@ -384,6 +393,7 @@ void cDvbPlayer::Action(void)
int Length = 0; int Length = 0;
bool Sleep = false; bool Sleep = false;
bool WaitingForData = false; bool WaitingForData = false;
time_t StuckAtEnd = 0;
while (Running() && (NextFile() || readIndex >= 0 || ringBuffer->Available() || !DeviceFlush(100))) { while (Running() && (NextFile() || readIndex >= 0 || ringBuffer->Available() || !DeviceFlush(100))) {
if (Sleep) { if (Sleep) {
@ -397,6 +407,8 @@ void cDvbPlayer::Action(void)
if (DevicePoll(Poller, 100)) { if (DevicePoll(Poller, 100)) {
LOCK_THREAD; LOCK_THREAD;
bool HitBegin = false;
bool HitEnd = false;
// Read the next frame from the file: // Read the next frame from the file:
@ -408,8 +420,9 @@ void cDvbPlayer::Action(void)
off_t FileOffset; off_t FileOffset;
bool TimeShiftMode = index->IsStillRecording(); bool TimeShiftMode = index->IsStillRecording();
int Index = -1; int Index = -1;
readIndependent = false;
if (DeviceHasIBPTrickSpeed() && playDir == pdForward) { if (DeviceHasIBPTrickSpeed() && playDir == pdForward) {
if (index->Get(readIndex + 1, &FileNumber, &FileOffset, NULL, &Length)) if (index->Get(readIndex + 1, &FileNumber, &FileOffset, &readIndependent, &Length))
Index = readIndex + 1; Index = readIndex + 1;
} }
else { else {
@ -417,42 +430,33 @@ void cDvbPlayer::Action(void)
if (playDir != pdForward) if (playDir != pdForward)
d = -d; d = -d;
Index = index->GetNextIFrame(readIndex + d, playDir == pdForward, &FileNumber, &FileOffset, &Length, TimeShiftMode); Index = index->GetNextIFrame(readIndex + d, playDir == pdForward, &FileNumber, &FileOffset, &Length, TimeShiftMode);
readIndependent = true;
} }
if (Index >= 0) { if (Index >= 0) {
if (!NextFile(FileNumber, FileOffset)) { readIndex = Index;
readIndex = Index; if (!NextFile(FileNumber, FileOffset))
continue; continue;
}
} }
else { else {
if (!TimeShiftMode && playDir == pdForward) { if (playDir == pdForward) {
// hit end of recording: signal end of file but don't change playMode if (!TimeShiftMode) {
readIndex = -1; // hit end of recording: signal end of file but don't change playMode
eof = true; eof = true;
continue; HitEnd = true;
}
} }
// hit begin of recording: wait for device buffers to drain else
// before changing play mode: HitBegin = true; // hit begin of recording - trigger wait until device has replayed the very first frame:
if (!DeviceFlush(100))
continue;
// can't call Play() here, because those functions may only be
// called from the foreground thread - and we also don't need
// to empty the buffer here
DevicePlay();
playMode = pmPlay;
playDir = pdForward;
continue;
} }
readIndex = Index;
} }
else if (index) { else if (index) {
uint16_t FileNumber; uint16_t FileNumber;
off_t FileOffset; off_t FileOffset;
readIndex++; if (index->Get(readIndex + 1, &FileNumber, &FileOffset, &readIndependent, &Length) && NextFile(FileNumber, FileOffset))
if (!(index->Get(readIndex, &FileNumber, &FileOffset, NULL, &Length) && NextFile(FileNumber, FileOffset))) { readIndex++;
readIndex = -1; else {
eof = true; eof = true;
continue; HitEnd = true;
} }
} }
else // allows replay even if the index file is missing else // allows replay even if the index file is missing
@ -465,19 +469,24 @@ void cDvbPlayer::Action(void)
} }
b = MALLOC(uchar, Length); b = MALLOC(uchar, Length);
} }
int r = nonBlockingFileReader->Read(replayFile, b, Length); if (!eof) {
if (r > 0) { int r = nonBlockingFileReader->Read(replayFile, b, Length);
WaitingForData = false; if (r > 0) {
readFrame = new cFrame(b, -r, ftUnknown, readIndex); // hands over b to the ringBuffer WaitingForData = false;
b = NULL; uint32_t Pts = 0;
} if (readIndependent)
else if (r == 0) Pts = isPesRecording ? PesGetPts(b) : TsGetPts(b, r);
eof = true; readFrame = new cFrame(b, -r, ftUnknown, readIndependent ? readIndex : -1, Pts); // hands over b to the ringBuffer
else if (r < 0 && errno == EAGAIN) b = NULL;
WaitingForData = true; }
else if (r < 0 && FATALERRNO) { else if (r == 0)
LOG_ERROR; eof = true;
break; else if (r < 0 && errno == EAGAIN)
WaitingForData = true;
else if (r < 0 && FATALERRNO) {
LOG_ERROR;
break;
}
} }
} }
@ -506,6 +515,8 @@ void cDvbPlayer::Action(void)
p = playFrame->Data(); p = playFrame->Data();
pc = playFrame->Count(); pc = playFrame->Count();
if (p) { if (p) {
if (playFrame->Index() >= 0)
ptsIndex.Put(playFrame->Pts(), playFrame->Index());
if (firstPacket) { if (firstPacket) {
if (isPesRecording) { if (isPesRecording) {
PlayPes(NULL, 0); PlayPes(NULL, 0);
@ -533,8 +544,6 @@ void cDvbPlayer::Action(void)
} }
} }
if (pc <= 0) { if (pc <= 0) {
writeIndex = playFrame->Index();
backTrace->Add(playFrame->Index(), playFrame->Count());
ringBuffer->Drop(playFrame); ringBuffer->Drop(playFrame);
playFrame = NULL; playFrame = NULL;
p = NULL; p = NULL;
@ -542,6 +551,31 @@ void cDvbPlayer::Action(void)
} }
else else
Sleep = true; Sleep = true;
// Handle hitting begin/end of recording:
if (HitBegin || HitEnd) {
if (DeviceFlush(10)) // give device a chance to display the last frame
cCondWait::SleepMs(10); // don't get into a tight loop
}
if (HitBegin) {
if (ptsIndex.FindIndex(DeviceGetSTC()) <= 0) {
Empty();
DevicePlay();
playMode = pmPlay;
playDir = pdForward;
}
}
else if (HitEnd) {
if (ptsIndex.FindIndex(DeviceGetSTC()) >= readIndex)
break;
else if (!StuckAtEnd)
StuckAtEnd = time(NULL);
else if (time(NULL) - StuckAtEnd > MAXSTUCKATEND)
break;
}
else
StuckAtEnd = 0;
} }
} }
@ -614,6 +648,7 @@ void cDvbPlayer::Forward(void)
Pause(); Pause();
break; break;
} }
Empty();
// run into pmPause // run into pmPause
case pmStill: case pmStill:
case pmPause: case pmPause:
@ -661,6 +696,7 @@ void cDvbPlayer::Backward(void)
Pause(); Pause();
break; break;
} }
Empty();
// run into pmPause // run into pmPause
case pmStill: case pmStill:
case pmPause: { case pmPause: {
@ -696,14 +732,14 @@ void cDvbPlayer::SkipSeconds(int Seconds)
{ {
if (index && Seconds) { if (index && Seconds) {
LOCK_THREAD; LOCK_THREAD;
int Index = ptsIndex.FindIndex(DeviceGetSTC());
Empty(); Empty();
int Index = writeIndex;
if (Index >= 0) { if (Index >= 0) {
Index = max(Index + SecondsToFrames(Seconds, framesPerSecond), 0); Index = max(Index + SecondsToFrames(Seconds, framesPerSecond), 0);
if (Index > 0) if (Index > 0)
Index = index->GetNextIFrame(Index, false, NULL, NULL, NULL, true); Index = index->GetNextIFrame(Index, false, NULL, NULL, NULL, true);
if (Index >= 0) if (Index >= 0)
readIndex = writeIndex = Index - 1; // Action() will first increment it! readIndex = Index - 1; // Action() will first increment it!
} }
Play(); Play();
} }
@ -727,25 +763,22 @@ void cDvbPlayer::Goto(int Index, bool Still)
if (playMode == pmPause) if (playMode == pmPause)
DevicePlay(); DevicePlay();
DeviceStillPicture(b, r); DeviceStillPicture(b, r);
ptsIndex.Put(isPesRecording ? PesGetPts(b) : TsGetPts(b, r), Index);
} }
playMode = pmStill; playMode = pmStill;
} }
readIndex = writeIndex = Index; readIndex = Index;
} }
} }
bool cDvbPlayer::GetIndex(int &Current, int &Total, bool SnapToIFrame) bool cDvbPlayer::GetIndex(int &Current, int &Total, bool SnapToIFrame)
{ {
if (index) { if (index) {
if (playMode == pmStill) Current = ptsIndex.FindIndex(DeviceGetSTC());
Current = max(readIndex, 0); if (SnapToIFrame) {
else { int i1 = index->GetNextIFrame(Current + 1, false);
Current = max(writeIndex, 0); int i2 = index->GetNextIFrame(Current, true);
if (SnapToIFrame) { Current = (abs(Current - i1) <= abs(Current - i2)) ? i1 : i2;
int i1 = index->GetNextIFrame(Current + 1, false);
int i2 = index->GetNextIFrame(Current, true);
Current = (abs(Current - i1) <= abs(Current - i2)) ? i1 : i2;
}
} }
Total = index->Last(); Total = index->Last();
return true; return true;

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: player.h 2.3 2009/01/25 11:03:44 kls Exp $ * $Id: player.h 2.4 2009/03/08 12:29:10 kls Exp $
*/ */
#ifndef __PLAYER_H #ifndef __PLAYER_H
@ -34,6 +34,7 @@ protected:
void DeviceMute(void) { if (device) device->Mute(); } void DeviceMute(void) { if (device) device->Mute(); }
void DeviceSetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat) { if (device) device->SetVideoDisplayFormat(VideoDisplayFormat); } void DeviceSetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat) { if (device) device->SetVideoDisplayFormat(VideoDisplayFormat); }
void DeviceStillPicture(const uchar *Data, int Length) { if (device) device->StillPicture(Data, Length); } void DeviceStillPicture(const uchar *Data, int Length) { if (device) device->StillPicture(Data, Length); }
uint64_t DeviceGetSTC(void) { return device ? device->GetSTC() : -1; }
void Detach(void); void Detach(void);
virtual void Activate(bool On) {} virtual void Activate(bool On) {}
// This function is called right after the cPlayer has been attached to // This function is called right after the cPlayer has been attached to

17
remux.c
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: remux.c 2.13 2009/01/24 13:44:45 kls Exp $ * $Id: remux.c 2.14 2009/03/08 12:12:17 kls Exp $
*/ */
#include "remux.h" #include "remux.h"
@ -109,6 +109,21 @@ void cRemux::SetBrokenLink(uchar *Data, int Length)
dsyslog("SetBrokenLink: no video packet in frame"); dsyslog("SetBrokenLink: no video packet in frame");
} }
// --- Some TS handling tools ------------------------------------------------
int64_t TsGetPts(const uchar *p, int l)
{
// Find the first packet with a PTS and use it:
while (l > 0) {
const uchar *d = p;
if (TsPayloadStart(d) && TsGetPayload(&d) && PesHasPts(d))
return PesGetPts(d);
p += TS_SIZE;
l -= TS_SIZE;
}
return -1;
}
// --- cPatPmtGenerator ------------------------------------------------------ // --- cPatPmtGenerator ------------------------------------------------------
cPatPmtGenerator::cPatPmtGenerator(cChannel *Channel) cPatPmtGenerator::cPatPmtGenerator(cChannel *Channel)

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: remux.h 2.7 2009/01/24 13:38:10 kls Exp $ * $Id: remux.h 2.8 2009/03/08 12:05:12 kls Exp $
*/ */
#ifndef __REMUX_H #ifndef __REMUX_H
@ -101,6 +101,10 @@ inline int TsGetAdaptationField(const uchar *p)
return TsHasAdaptationField(p) ? p[5] : 0x00; return TsHasAdaptationField(p) ? p[5] : 0x00;
} }
// The following functions all take a pointer to a sequence of complete TS packets.
int64_t TsGetPts(const uchar *p, int l);
// Some PES handling tools: // Some PES handling tools:
// The following functions that take a pointer to PES data all assume that // The following functions that take a pointer to PES data all assume that
// there is enough data so that PesLongEnough() returns true. // there is enough data so that PesLongEnough() returns true.

View File

@ -7,7 +7,7 @@
* Parts of this file were inspired by the 'ringbuffy.c' from the * Parts of this file were inspired by the 'ringbuffy.c' from the
* LinuxDVB driver (see linuxtv.org). * LinuxDVB driver (see linuxtv.org).
* *
* $Id: ringbuffer.c 1.25 2007/11/17 13:49:34 kls Exp $ * $Id: ringbuffer.c 2.1 2009/03/01 11:20:34 kls Exp $
*/ */
#include "ringbuffer.h" #include "ringbuffer.h"
@ -335,11 +335,12 @@ void cRingBufferLinear::Del(int Count)
// --- cFrame ---------------------------------------------------------------- // --- cFrame ----------------------------------------------------------------
cFrame::cFrame(const uchar *Data, int Count, eFrameType Type, int Index) cFrame::cFrame(const uchar *Data, int Count, eFrameType Type, int Index, uint32_t Pts)
{ {
count = abs(Count); count = abs(Count);
type = Type; type = Type;
index = Index; index = Index;
pts = Pts;
if (Count < 0) if (Count < 0)
data = (uchar *)Data; data = (uchar *)Data;
else { else {

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: ringbuffer.h 1.18 2007/11/17 13:49:34 kls Exp $ * $Id: ringbuffer.h 2.1 2009/03/01 11:20:34 kls Exp $
*/ */
#ifndef __RINGBUFFER_H #ifndef __RINGBUFFER_H
@ -108,8 +108,9 @@ private:
int count; int count;
eFrameType type; eFrameType type;
int index; int index;
uint32_t pts;
public: public:
cFrame(const uchar *Data, int Count, eFrameType = ftUnknown, int Index = -1); cFrame(const uchar *Data, int Count, eFrameType = ftUnknown, int Index = -1, uint32_t Pts = 0);
///< Creates a new cFrame object. ///< Creates a new cFrame object.
///< If Count is negative, the cFrame object will take ownership of the given ///< If Count is negative, the cFrame object will take ownership of the given
///< Data. Otherwise it will allocate Count bytes of memory and copy Data. ///< Data. Otherwise it will allocate Count bytes of memory and copy Data.
@ -118,6 +119,7 @@ public:
int Count(void) const { return count; } int Count(void) const { return count; }
eFrameType Type(void) const { return type; } eFrameType Type(void) const { return type; }
int Index(void) const { return index; } int Index(void) const { return index; }
uint32_t Pts(void) const { return pts; }
}; };
class cRingBufferFrame : public cRingBuffer { class cRingBufferFrame : public cRingBuffer {