From f3e6d393829878980eea821a068ef04a5ac5adf4 Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Fri, 6 Feb 2015 15:42:21 +0100 Subject: [PATCH] cDvbPlayer and cReplayControl now use the same list of editing marks --- HISTORY | 3 +++ MANUAL | 4 ---- dvbplayer.c | 46 ++++++++++++++++++++++++++++++++-------------- dvbplayer.h | 4 +++- menu.c | 8 +++++++- recording.c | 9 ++++++++- recording.h | 14 ++++++++++++-- 7 files changed, 65 insertions(+), 23 deletions(-) diff --git a/HISTORY b/HISTORY index 75cf676a..cc737bf0 100644 --- a/HISTORY +++ b/HISTORY @@ -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. diff --git a/MANUAL b/MANUAL index f329a771..b0b7fa59 100644 --- a/MANUAL +++ b/MANUAL @@ -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 diff --git a/dvbplayer.c b/dvbplayer.c index 9e561ca1..94882e29 100644 --- a/dvbplayer.c +++ b/dvbplayer.c @@ -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 #include -#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(); diff --git a/dvbplayer.h b/dvbplayer.h index 678c9693..7094454d 100644 --- a/dvbplayer.h +++ b/dvbplayer.h @@ -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). diff --git a/menu.c b/menu.c index 6cda42d0..fd18c1bb 100644 --- a/menu.c +++ b/menu.c @@ -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); diff --git a/recording.c b/recording.c index 19b36db8..271f6475 100644 --- a/recording.c +++ b/recording.c @@ -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::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::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)) { diff --git a/recording.h b/recording.h index 1079ae1f..f6eaa19b 100644 --- a/recording.h +++ b/recording.h @@ -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 { +class cMarks : public cConfig, 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