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. process.
- Changed the naming of "binary skip mode" to "adaptive skip mode" (suggested by - Changed the naming of "binary skip mode" to "adaptive skip mode" (suggested by
Rolf Ahrenberg and Derek Kelly). 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 automatically skipped during replay. This includes jumping
to the first mark if replay starts at the beginning of the to the first mark if replay starts at the beginning of the
recording, and stopping at the last mark. 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 Pause replay at last mark = no
If enabled, replay of a recording will go into Pause mode 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 the actual position at which the pause occurs may be a couple
of frames before the last "end" mark, depending on how much of frames before the last "end" mark, depending on how much
data is buffered by your output device. 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 Initial duration for adaptive skipping (s) = 120
Defines the number of seconds to jump from the current replay 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 * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 "dvbplayer.h"
#include <math.h> #include <math.h>
#include <stdlib.h> #include <stdlib.h>
#include "recording.h"
#include "remux.h" #include "remux.h"
#include "ringbuffer.h" #include "ringbuffer.h"
#include "thread.h" #include "thread.h"
@ -211,7 +210,7 @@ private:
cNonBlockingFileReader *nonBlockingFileReader; cNonBlockingFileReader *nonBlockingFileReader;
cRingBufferFrame *ringBuffer; cRingBufferFrame *ringBuffer;
cPtsIndex ptsIndex; cPtsIndex ptsIndex;
cMarks marks; cMarks *marks;
cFileName *fileName; cFileName *fileName;
cIndexFile *index; cIndexFile *index;
cUnbufferedFile *replayFile; cUnbufferedFile *replayFile;
@ -240,6 +239,7 @@ protected:
public: public:
cDvbPlayer(const char *FileName, bool PauseLive); cDvbPlayer(const char *FileName, bool PauseLive);
virtual ~cDvbPlayer(); virtual ~cDvbPlayer();
void SetMarks(cMarks *Marks);
bool Active(void) { return cThread::Running(); } bool Active(void) { return cThread::Running(); }
void Pause(void); void Pause(void);
void Play(void); void Play(void);
@ -265,6 +265,7 @@ cDvbPlayer::cDvbPlayer(const char *FileName, bool PauseLive)
{ {
nonBlockingFileReader = NULL; nonBlockingFileReader = NULL;
ringBuffer = NULL; ringBuffer = NULL;
marks = NULL;
index = NULL; index = NULL;
cRecording Recording(FileName); cRecording Recording(FileName);
framesPerSecond = Recording.FramesPerSecond(); framesPerSecond = Recording.FramesPerSecond();
@ -297,8 +298,6 @@ cDvbPlayer::cDvbPlayer(const char *FileName, bool PauseLive)
} }
else if (PauseLive) else if (PauseLive)
framesPerSecond = cRecording(FileName).FramesPerSecond(); // the fps rate might have changed from the default 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() cDvbPlayer::~cDvbPlayer()
@ -309,6 +308,12 @@ cDvbPlayer::~cDvbPlayer()
delete index; delete index;
delete fileName; delete fileName;
delete ringBuffer; delete ringBuffer;
// don't delete marks here, we don't own them!
}
void cDvbPlayer::SetMarks(cMarks *Marks)
{
marks = Marks;
} }
void cDvbPlayer::TrickSpeed(int Increment) void cDvbPlayer::TrickSpeed(int Increment)
@ -377,8 +382,12 @@ bool cDvbPlayer::Save(void)
if (index) { if (index) {
int Index = ptsIndex.FindIndex(DeviceGetSTC()); int Index = ptsIndex.FindIndex(DeviceGetSTC());
if (Index >= 0) { if (Index >= 0) {
if (Setup.SkipEdited && marks.First() && abs(Index - marks.First()->Position()) <= int(round(RESUMEBACKUP * framesPerSecond))) if (Setup.SkipEdited && marks) {
Index = 0; // when stopping within RESUMEBACKUP seconds of the first mark the recording shall still be considered unviewed 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)); Index -= int(round(RESUMEBACKUP * framesPerSecond));
if (Index > 0) if (Index > 0)
Index = index->GetNextIFrame(Index, false); Index = index->GetNextIFrame(Index, false);
@ -409,9 +418,10 @@ void cDvbPlayer::Action(void)
readIndex = Resume(); readIndex = Resume();
if (readIndex > 0) if (readIndex > 0)
isyslog("resuming replay at index %d (%s)", readIndex, *IndexToHMSF(readIndex, true, framesPerSecond)); isyslog("resuming replay at index %d (%s)", readIndex, *IndexToHMSF(readIndex, true, framesPerSecond));
else if (Setup.SkipEdited) { else if (Setup.SkipEdited && marks) {
if (marks.First() && index) { marks->Lock();
int Index = marks.First()->Position(); if (marks->First() && index) {
int Index = marks->First()->Position();
uint16_t FileNumber; uint16_t FileNumber;
off_t FileOffset; off_t FileOffset;
if (index->Get(Index, &FileNumber, &FileOffset) && NextFile(FileNumber, FileOffset)) { if (index->Get(Index, &FileNumber, &FileOffset) && NextFile(FileNumber, FileOffset)) {
@ -419,6 +429,7 @@ void cDvbPlayer::Action(void)
readIndex = Index; readIndex = Index;
} }
} }
marks->Unlock();
} }
nonBlockingFileReader = new cNonBlockingFileReader; nonBlockingFileReader = new cNonBlockingFileReader;
@ -488,11 +499,11 @@ void cDvbPlayer::Action(void)
off_t FileOffset; off_t FileOffset;
if (index->Get(readIndex + 1, &FileNumber, &FileOffset, &readIndependent, &Length) && NextFile(FileNumber, FileOffset)) { if (index->Get(readIndex + 1, &FileNumber, &FileOffset, &readIndependent, &Length) && NextFile(FileNumber, FileOffset)) {
readIndex++; readIndex++;
if (Setup.SkipEdited || Setup.PauseAtLastMark) { if ((Setup.SkipEdited || Setup.PauseAtLastMark) && marks) {
marks.Update(); marks->Lock();
cMark *m = marks.Get(readIndex); cMark *m = marks->Get(readIndex);
if (m && (m->Index() & 0x01) != 0) { // we're at an end mark if (m && (m->Index() & 0x01) != 0) { // we're at an end mark
m = marks.GetNextBegin(m); m = marks->GetNextBegin(m);
int Index = -1; int Index = -1;
if (m) if (m)
Index = m->Position(); // skip to next begin mark Index = m->Position(); // skip to next begin mark
@ -508,6 +519,7 @@ void cDvbPlayer::Action(void)
CutIn = true; CutIn = true;
} }
} }
marks->Unlock();
} }
} }
else else
@ -931,6 +943,12 @@ cDvbPlayerControl::~cDvbPlayerControl()
Stop(); Stop();
} }
void cDvbPlayerControl::SetMarks(cMarks *Marks)
{
if (player)
player->SetMarks(Marks);
}
bool cDvbPlayerControl::Active(void) bool cDvbPlayerControl::Active(void)
{ {
return player && player->Active(); return player && player->Active();

View File

@ -4,13 +4,14 @@
* 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.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 #ifndef __DVBPLAYER_H
#define __DVBPLAYER_H #define __DVBPLAYER_H
#include "player.h" #include "player.h"
#include "recording.h"
#include "thread.h" #include "thread.h"
class cDvbPlayer; class cDvbPlayer;
@ -25,6 +26,7 @@ public:
// file of the recording is long enough to allow the player to display // file of the recording is long enough to allow the player to display
// the first frame in still picture mode. // the first frame in still picture mode.
virtual ~cDvbPlayerControl(); virtual ~cDvbPlayerControl();
void SetMarks(cMarks *Marks);
bool Active(void); bool Active(void);
void Stop(void); void Stop(void);
// Stops the current replay session (if any). // 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 * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "menu.h"
@ -5120,6 +5120,7 @@ cReplayControl::cReplayControl(bool PauseLive)
cRecording Recording(fileName); cRecording Recording(fileName);
cStatus::MsgReplaying(this, Recording.Name(), Recording.FileName(), true); cStatus::MsgReplaying(this, Recording.Name(), Recording.FileName(), true);
marks.Load(fileName, Recording.FramesPerSecond(), Recording.IsPesRecording()); marks.Load(fileName, Recording.FramesPerSecond(), Recording.IsPesRecording());
SetMarks(&marks);
adaptiveSkipper.Initialize(&Setup.AdaptiveSkipInitial, Recording.FramesPerSecond()); adaptiveSkipper.Initialize(&Setup.AdaptiveSkipInitial, Recording.FramesPerSecond());
SetTrackDescriptions(false); SetTrackDescriptions(false);
if (Setup.ProgressDisplayTime) if (Setup.ProgressDisplayTime)
@ -5389,6 +5390,7 @@ void cReplayControl::MarkToggle(void)
int Current, Total; int Current, Total;
if (GetIndex(Current, Total, true)) { if (GetIndex(Current, Total, true)) {
lastCurrent = -1; // triggers redisplay lastCurrent = -1; // triggers redisplay
cMutexLock MutexLock(&marks);
if (cMark *m = marks.Get(Current)) if (cMark *m = marks.Get(Current))
marks.Del(m); marks.Del(m);
else { else {
@ -5409,6 +5411,7 @@ void cReplayControl::MarkJump(bool Forward)
{ {
int Current, Total; int Current, Total;
if (GetIndex(Current, Total)) { if (GetIndex(Current, Total)) {
cMutexLock MutexLock(&marks);
if (marks.Count()) { if (marks.Count()) {
if (cMark *m = Forward ? marks.GetNext(Current) : marks.GetPrev(Current)) { if (cMark *m = Forward ? marks.GetNext(Current) : marks.GetPrev(Current)) {
if (!Setup.PauseOnMarkJump) { if (!Setup.PauseOnMarkJump) {
@ -5437,6 +5440,7 @@ void cReplayControl::MarkMove(int Frames, bool MarkRequired)
bool Play, Forward; bool Play, Forward;
int Speed; int Speed;
GetReplayMode(Play, Forward, Speed); GetReplayMode(Play, Forward, Speed);
cMutexLock MutexLock(&marks);
cMark *m = marks.Get(Current); cMark *m = marks.Get(Current);
if (!Play && m) { if (!Play && m) {
displayFrames = true; displayFrames = true;
@ -5472,6 +5476,7 @@ void cReplayControl::EditCut(void)
if (*fileName) { if (*fileName) {
Hide(); Hide();
if (!RecordingsHandler.GetUsage(fileName)) { if (!RecordingsHandler.GetUsage(fileName)) {
cMutexLock MutexLock(&marks);
if (!marks.Count()) if (!marks.Count())
Skins.Message(mtError, tr("No editing marks defined!")); Skins.Message(mtError, tr("No editing marks defined!"));
else if (!marks.GetNumSequences()) else if (!marks.GetNumSequences())
@ -5493,6 +5498,7 @@ void cReplayControl::EditTest(void)
{ {
int Current, Total; int Current, Total;
if (GetIndex(Current, Total)) { if (GetIndex(Current, Total)) {
cMutexLock MutexLock(&marks);
cMark *m = marks.Get(Current); cMark *m = marks.Get(Current);
if (!m) if (!m)
m = marks.GetNext(Current); m = marks.GetNext(Current);

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: 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" #include "recording.h"
@ -2059,6 +2059,7 @@ cString cMarks::MarksFileName(const cRecording *Recording)
bool cMarks::Load(const char *RecordingFileName, double FramesPerSecond, bool IsPesRecording) bool cMarks::Load(const char *RecordingFileName, double FramesPerSecond, bool IsPesRecording)
{ {
cMutexLock MutexLock(this);
recordingFileName = RecordingFileName; recordingFileName = RecordingFileName;
fileName = AddDirectory(RecordingFileName, IsPesRecording ? MARKSFILESUFFIX ".vdr" : MARKSFILESUFFIX); fileName = AddDirectory(RecordingFileName, IsPesRecording ? MARKSFILESUFFIX ".vdr" : MARKSFILESUFFIX);
framesPerSecond = FramesPerSecond; framesPerSecond = FramesPerSecond;
@ -2071,6 +2072,7 @@ bool cMarks::Load(const char *RecordingFileName, double FramesPerSecond, bool Is
bool cMarks::Update(void) bool cMarks::Update(void)
{ {
cMutexLock MutexLock(this);
time_t t = time(NULL); time_t t = time(NULL);
if (t > nextUpdate && *fileName) { if (t > nextUpdate && *fileName) {
time_t LastModified = LastModifiedTime(fileName); time_t LastModified = LastModifiedTime(fileName);
@ -2102,6 +2104,7 @@ bool cMarks::Update(void)
bool cMarks::Save(void) bool cMarks::Save(void)
{ {
cMutexLock MutexLock(this);
if (cConfig<cMark>::Save()) { if (cConfig<cMark>::Save()) {
lastFileTime = LastModifiedTime(fileName); lastFileTime = LastModifiedTime(fileName);
return true; return true;
@ -2111,6 +2114,7 @@ bool cMarks::Save(void)
void cMarks::Align(void) void cMarks::Align(void)
{ {
cMutexLock MutexLock(this);
cIndexFile IndexFile(recordingFileName, false, isPesRecording); cIndexFile IndexFile(recordingFileName, false, isPesRecording);
for (cMark *m = First(); m; m = Next(m)) { for (cMark *m = First(); m; m = Next(m)) {
int p = IndexFile.GetClosestIFrame(m->Position()); int p = IndexFile.GetClosestIFrame(m->Position());
@ -2123,6 +2127,7 @@ void cMarks::Align(void)
void cMarks::Sort(void) void cMarks::Sort(void)
{ {
cMutexLock MutexLock(this);
for (cMark *m1 = First(); m1; m1 = Next(m1)) { for (cMark *m1 = First(); m1; m1 = Next(m1)) {
for (cMark *m2 = Next(m1); m2; m2 = Next(m2)) { for (cMark *m2 = Next(m1); m2; m2 = Next(m2)) {
if (m2->Position() < m1->Position()) { if (m2->Position() < m1->Position()) {
@ -2135,6 +2140,7 @@ void cMarks::Sort(void)
void cMarks::Add(int Position) void cMarks::Add(int Position)
{ {
cMutexLock MutexLock(this);
cConfig<cMark>::Add(new cMark(Position, NULL, framesPerSecond)); cConfig<cMark>::Add(new cMark(Position, NULL, framesPerSecond));
Sort(); Sort();
} }
@ -2202,6 +2208,7 @@ cMark *cMarks::GetNextEnd(cMark *BeginMark)
int cMarks::GetNumSequences(void) int cMarks::GetNumSequences(void)
{ {
cMutexLock MutexLock(this);
int NumSequences = 0; int NumSequences = 0;
if (cMark *BeginMark = GetNextBegin()) { if (cMark *BeginMark = GetNextBegin()) {
while (cMark *EndMark = GetNextEnd(BeginMark)) { while (cMark *EndMark = GetNextEnd(BeginMark)) {

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: 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 #ifndef __RECORDING_H
@ -350,7 +350,7 @@ public:
bool Save(FILE *f); bool Save(FILE *f);
}; };
class cMarks : public cConfig<cMark> { class cMarks : public cConfig<cMark>, public cMutex {
private: private:
cString recordingFileName; cString recordingFileName;
cString fileName; cString fileName;
@ -370,15 +370,25 @@ public:
void Sort(void); void Sort(void);
void Add(int Position); void Add(int Position);
cMark *Get(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); 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); 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); cMark *GetNextBegin(cMark *EndMark = NULL);
///< Returns the next "begin" mark after EndMark, skipping any marks at the ///< Returns the next "begin" mark after EndMark, skipping any marks at the
///< same position as EndMark. If EndMark is NULL, the first actual "begin" ///< same position as EndMark. If EndMark is NULL, the first actual "begin"
///< will be returned (if any). ///< 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); cMark *GetNextEnd(cMark *BeginMark);
///< Returns the next "end" mark after BeginMark, skipping any marks at the ///< Returns the next "end" mark after BeginMark, skipping any marks at the
///< same position as BeginMark. ///< 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); int GetNumSequences(void);
///< Returns the actual number of sequences to be cut from the recording. ///< 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 ///< If there is only one actual "begin" mark, and it is positioned at index