cDvbPlayer and cReplayControl now use the same list of editing marks

This commit is contained in:
Klaus Schmidinger 2015-02-06 15:42:21 +01:00
parent 4ffd2d6ccd
commit f3e6d39382
7 changed files with 65 additions and 23 deletions

View File

@ -8508,3 +8508,6 @@ Video Disk Recorder Revision History
process.
- Changed the naming of "binary skip mode" to "adaptive skip mode" (suggested by
Rolf Ahrenberg and Derek Kelly).
- cDvbPlayer and cReplayControl now use the same list of editing marks. This avoids
inconsistent behavior with the "Skip edited parts" or "Pause replay at last mark"
functions when the editing marks are manipulated during replay.

4
MANUAL
View File

@ -991,8 +991,6 @@ Version 2.0
automatically skipped during replay. This includes jumping
to the first mark if replay starts at the beginning of the
recording, and stopping at the last mark.
In order to work, this option must be enabled before starting
replay.
Pause replay at last mark = no
If enabled, replay of a recording will go into Pause mode
@ -1000,8 +998,6 @@ Version 2.0
the actual position at which the pause occurs may be a couple
of frames before the last "end" mark, depending on how much
data is buffered by your output device.
In order to work, this option must be enabled before starting
replay.
Initial duration for adaptive skipping (s) = 120
Defines the number of seconds to jump from the current replay

View File

@ -4,13 +4,12 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: dvbplayer.c 3.4 2015/02/02 09:51:32 kls Exp $
* $Id: dvbplayer.c 3.5 2015/02/06 15:08:51 kls Exp $
*/
#include "dvbplayer.h"
#include <math.h>
#include <stdlib.h>
#include "recording.h"
#include "remux.h"
#include "ringbuffer.h"
#include "thread.h"
@ -211,7 +210,7 @@ private:
cNonBlockingFileReader *nonBlockingFileReader;
cRingBufferFrame *ringBuffer;
cPtsIndex ptsIndex;
cMarks marks;
cMarks *marks;
cFileName *fileName;
cIndexFile *index;
cUnbufferedFile *replayFile;
@ -240,6 +239,7 @@ protected:
public:
cDvbPlayer(const char *FileName, bool PauseLive);
virtual ~cDvbPlayer();
void SetMarks(cMarks *Marks);
bool Active(void) { return cThread::Running(); }
void Pause(void);
void Play(void);
@ -265,6 +265,7 @@ cDvbPlayer::cDvbPlayer(const char *FileName, bool PauseLive)
{
nonBlockingFileReader = NULL;
ringBuffer = NULL;
marks = NULL;
index = NULL;
cRecording Recording(FileName);
framesPerSecond = Recording.FramesPerSecond();
@ -297,8 +298,6 @@ cDvbPlayer::cDvbPlayer(const char *FileName, bool PauseLive)
}
else if (PauseLive)
framesPerSecond = cRecording(FileName).FramesPerSecond(); // the fps rate might have changed from the default
if (Setup.SkipEdited || Setup.PauseAtLastMark)
marks.Load(FileName, framesPerSecond, isPesRecording);
}
cDvbPlayer::~cDvbPlayer()
@ -309,6 +308,12 @@ cDvbPlayer::~cDvbPlayer()
delete index;
delete fileName;
delete ringBuffer;
// don't delete marks here, we don't own them!
}
void cDvbPlayer::SetMarks(cMarks *Marks)
{
marks = Marks;
}
void cDvbPlayer::TrickSpeed(int Increment)
@ -377,8 +382,12 @@ bool cDvbPlayer::Save(void)
if (index) {
int Index = ptsIndex.FindIndex(DeviceGetSTC());
if (Index >= 0) {
if (Setup.SkipEdited && marks.First() && abs(Index - marks.First()->Position()) <= int(round(RESUMEBACKUP * framesPerSecond)))
Index = 0; // when stopping within RESUMEBACKUP seconds of the first mark the recording shall still be considered unviewed
if (Setup.SkipEdited && marks) {
marks->Lock();
if (marks->First() && abs(Index - marks->First()->Position()) <= int(round(RESUMEBACKUP * framesPerSecond)))
Index = 0; // when stopping within RESUMEBACKUP seconds of the first mark the recording shall still be considered unviewed
marks->Unlock();
}
Index -= int(round(RESUMEBACKUP * framesPerSecond));
if (Index > 0)
Index = index->GetNextIFrame(Index, false);
@ -409,9 +418,10 @@ void cDvbPlayer::Action(void)
readIndex = Resume();
if (readIndex > 0)
isyslog("resuming replay at index %d (%s)", readIndex, *IndexToHMSF(readIndex, true, framesPerSecond));
else if (Setup.SkipEdited) {
if (marks.First() && index) {
int Index = marks.First()->Position();
else if (Setup.SkipEdited && marks) {
marks->Lock();
if (marks->First() && index) {
int Index = marks->First()->Position();
uint16_t FileNumber;
off_t FileOffset;
if (index->Get(Index, &FileNumber, &FileOffset) && NextFile(FileNumber, FileOffset)) {
@ -419,6 +429,7 @@ void cDvbPlayer::Action(void)
readIndex = Index;
}
}
marks->Unlock();
}
nonBlockingFileReader = new cNonBlockingFileReader;
@ -488,11 +499,11 @@ void cDvbPlayer::Action(void)
off_t FileOffset;
if (index->Get(readIndex + 1, &FileNumber, &FileOffset, &readIndependent, &Length) && NextFile(FileNumber, FileOffset)) {
readIndex++;
if (Setup.SkipEdited || Setup.PauseAtLastMark) {
marks.Update();
cMark *m = marks.Get(readIndex);
if ((Setup.SkipEdited || Setup.PauseAtLastMark) && marks) {
marks->Lock();
cMark *m = marks->Get(readIndex);
if (m && (m->Index() & 0x01) != 0) { // we're at an end mark
m = marks.GetNextBegin(m);
m = marks->GetNextBegin(m);
int Index = -1;
if (m)
Index = m->Position(); // skip to next begin mark
@ -508,6 +519,7 @@ void cDvbPlayer::Action(void)
CutIn = true;
}
}
marks->Unlock();
}
}
else
@ -931,6 +943,12 @@ cDvbPlayerControl::~cDvbPlayerControl()
Stop();
}
void cDvbPlayerControl::SetMarks(cMarks *Marks)
{
if (player)
player->SetMarks(Marks);
}
bool cDvbPlayerControl::Active(void)
{
return player && player->Active();

View File

@ -4,13 +4,14 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: dvbplayer.h 3.1 2015/02/01 11:20:54 kls Exp $
* $Id: dvbplayer.h 3.2 2015/02/06 12:27:39 kls Exp $
*/
#ifndef __DVBPLAYER_H
#define __DVBPLAYER_H
#include "player.h"
#include "recording.h"
#include "thread.h"
class cDvbPlayer;
@ -25,6 +26,7 @@ public:
// file of the recording is long enough to allow the player to display
// the first frame in still picture mode.
virtual ~cDvbPlayerControl();
void SetMarks(cMarks *Marks);
bool Active(void);
void Stop(void);
// Stops the current replay session (if any).

8
menu.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: menu.c 3.42 2015/02/06 09:53:25 kls Exp $
* $Id: menu.c 3.43 2015/02/06 15:20:11 kls Exp $
*/
#include "menu.h"
@ -5120,6 +5120,7 @@ cReplayControl::cReplayControl(bool PauseLive)
cRecording Recording(fileName);
cStatus::MsgReplaying(this, Recording.Name(), Recording.FileName(), true);
marks.Load(fileName, Recording.FramesPerSecond(), Recording.IsPesRecording());
SetMarks(&marks);
adaptiveSkipper.Initialize(&Setup.AdaptiveSkipInitial, Recording.FramesPerSecond());
SetTrackDescriptions(false);
if (Setup.ProgressDisplayTime)
@ -5389,6 +5390,7 @@ void cReplayControl::MarkToggle(void)
int Current, Total;
if (GetIndex(Current, Total, true)) {
lastCurrent = -1; // triggers redisplay
cMutexLock MutexLock(&marks);
if (cMark *m = marks.Get(Current))
marks.Del(m);
else {
@ -5409,6 +5411,7 @@ void cReplayControl::MarkJump(bool Forward)
{
int Current, Total;
if (GetIndex(Current, Total)) {
cMutexLock MutexLock(&marks);
if (marks.Count()) {
if (cMark *m = Forward ? marks.GetNext(Current) : marks.GetPrev(Current)) {
if (!Setup.PauseOnMarkJump) {
@ -5437,6 +5440,7 @@ void cReplayControl::MarkMove(int Frames, bool MarkRequired)
bool Play, Forward;
int Speed;
GetReplayMode(Play, Forward, Speed);
cMutexLock MutexLock(&marks);
cMark *m = marks.Get(Current);
if (!Play && m) {
displayFrames = true;
@ -5472,6 +5476,7 @@ void cReplayControl::EditCut(void)
if (*fileName) {
Hide();
if (!RecordingsHandler.GetUsage(fileName)) {
cMutexLock MutexLock(&marks);
if (!marks.Count())
Skins.Message(mtError, tr("No editing marks defined!"));
else if (!marks.GetNumSequences())
@ -5493,6 +5498,7 @@ void cReplayControl::EditTest(void)
{
int Current, Total;
if (GetIndex(Current, Total)) {
cMutexLock MutexLock(&marks);
cMark *m = marks.Get(Current);
if (!m)
m = marks.GetNext(Current);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: recording.c 3.25 2015/02/05 13:50:39 kls Exp $
* $Id: recording.c 3.26 2015/02/06 15:13:59 kls Exp $
*/
#include "recording.h"
@ -2059,6 +2059,7 @@ cString cMarks::MarksFileName(const cRecording *Recording)
bool cMarks::Load(const char *RecordingFileName, double FramesPerSecond, bool IsPesRecording)
{
cMutexLock MutexLock(this);
recordingFileName = RecordingFileName;
fileName = AddDirectory(RecordingFileName, IsPesRecording ? MARKSFILESUFFIX ".vdr" : MARKSFILESUFFIX);
framesPerSecond = FramesPerSecond;
@ -2071,6 +2072,7 @@ bool cMarks::Load(const char *RecordingFileName, double FramesPerSecond, bool Is
bool cMarks::Update(void)
{
cMutexLock MutexLock(this);
time_t t = time(NULL);
if (t > nextUpdate && *fileName) {
time_t LastModified = LastModifiedTime(fileName);
@ -2102,6 +2104,7 @@ bool cMarks::Update(void)
bool cMarks::Save(void)
{
cMutexLock MutexLock(this);
if (cConfig<cMark>::Save()) {
lastFileTime = LastModifiedTime(fileName);
return true;
@ -2111,6 +2114,7 @@ bool cMarks::Save(void)
void cMarks::Align(void)
{
cMutexLock MutexLock(this);
cIndexFile IndexFile(recordingFileName, false, isPesRecording);
for (cMark *m = First(); m; m = Next(m)) {
int p = IndexFile.GetClosestIFrame(m->Position());
@ -2123,6 +2127,7 @@ void cMarks::Align(void)
void cMarks::Sort(void)
{
cMutexLock MutexLock(this);
for (cMark *m1 = First(); m1; m1 = Next(m1)) {
for (cMark *m2 = Next(m1); m2; m2 = Next(m2)) {
if (m2->Position() < m1->Position()) {
@ -2135,6 +2140,7 @@ void cMarks::Sort(void)
void cMarks::Add(int Position)
{
cMutexLock MutexLock(this);
cConfig<cMark>::Add(new cMark(Position, NULL, framesPerSecond));
Sort();
}
@ -2202,6 +2208,7 @@ cMark *cMarks::GetNextEnd(cMark *BeginMark)
int cMarks::GetNumSequences(void)
{
cMutexLock MutexLock(this);
int NumSequences = 0;
if (cMark *BeginMark = GetNextBegin()) {
while (cMark *EndMark = GetNextEnd(BeginMark)) {

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: recording.h 3.6 2015/01/31 13:34:44 kls Exp $
* $Id: recording.h 3.7 2015/02/06 15:17:04 kls Exp $
*/
#ifndef __RECORDING_H
@ -350,7 +350,7 @@ public:
bool Save(FILE *f);
};
class cMarks : public cConfig<cMark> {
class cMarks : public cConfig<cMark>, public cMutex {
private:
cString recordingFileName;
cString fileName;
@ -370,15 +370,25 @@ public:
void Sort(void);
void Add(int Position);
cMark *Get(int Position);
///< If this cMarks object is used by multiple threads, the caller must hold a lock
///< on this object as long as it handles the returned pointer.
cMark *GetPrev(int Position);
///< If this cMarks object is used by multiple threads, the caller must hold a lock
///< on this object as long as it handles the returned pointer.
cMark *GetNext(int Position);
///< If this cMarks object is used by multiple threads, the caller must hold a lock
///< on this object as long as it handles the returned pointer.
cMark *GetNextBegin(cMark *EndMark = NULL);
///< Returns the next "begin" mark after EndMark, skipping any marks at the
///< same position as EndMark. If EndMark is NULL, the first actual "begin"
///< will be returned (if any).
///< If this cMarks object is used by multiple threads, the caller must hold a lock
///< on this object as long as it handles the returned pointer.
cMark *GetNextEnd(cMark *BeginMark);
///< Returns the next "end" mark after BeginMark, skipping any marks at the
///< same position as BeginMark.
///< If this cMarks object is used by multiple threads, the caller must hold a lock
///< on this object as long as it handles the returned pointer.
int GetNumSequences(void);
///< Returns the actual number of sequences to be cut from the recording.
///< If there is only one actual "begin" mark, and it is positioned at index